Compare commits

...

137 Commits

Author SHA1 Message Date
Tschipp
de388366ca Updated Version 2025-12-31 09:57:34 +01:00
Tschipp
b66040bf03 Fixed wrong Packet ID for Carry Data Sync on Forge, Proper handling of carried player dying 2025-12-29 23:27:04 +01:00
Tschipp
47910dbf61 Added possibility for scripts to override certain pickup checks. Closes #853 2025-12-29 23:23:28 +01:00
Tschipp
f147e801cc Updated to 1.21.11 2025-12-27 23:25:58 +01:00
Tschipp
20a40c1487
Update issue templates 2025-12-27 23:00:46 +01:00
Tschipp
08bc465d82 Fixed bugs, updated Blacklist 2025-12-26 15:56:13 +01:00
Tschipp
3352c497e2 Merge branch 'CatsSomeCat-1.21.8' into 1.21.9 2025-12-25 16:30:41 +01:00
Tschipp
f58829ea21 Merge branch '1.21.8' of github.com:CatsSomeCat/CarryOn into CatsSomeCat-1.21.8
# Conflicts:
#	Common/src/main/java/tschipp/carryon/common/carry/PlacementHandler.java
#	Fabric/src/main/java/tschipp/carryon/CarryOnFabricMod.java
#	Fabric/src/main/java/tschipp/carryon/events/CommonEvents.java
#	gradle.properties
2025-12-25 16:29:06 +01:00
Tschipp
550940b4ab Fixed Sync Issue after Respawning #850 #845 #843 2025-12-25 14:19:05 +01:00
Tschipp
4ca8a885da Cleaned up fork code, restored carry transformations 2025-12-24 22:29:30 +01:00
Tschipp
326880d40b Merge branch 'Hanro50-1.21.9' into 1.21.9 2025-12-23 11:53:20 +01:00
Tschipp
d4e0b29a06 Merge branch '1.21.9' of github.com:Hanro50/CarryOn into Hanro50-1.21.9
# Conflicts:
#	Common/src/main/java/tschipp/carryon/CarryOnCommon.java
#	Common/src/main/java/tschipp/carryon/CarryOnCommonClient.java
#	Common/src/main/java/tschipp/carryon/client/keybinds/ConflictFreeKeyMapping.java
#	Common/src/main/java/tschipp/carryon/client/render/CarriedObjectRender.java
#	Common/src/main/java/tschipp/carryon/mixin/AvatarRenderStateMixin.java
#	Common/src/main/java/tschipp/carryon/mixin/HumanoidModelMixin.java
#	Common/src/main/resources/carryon.mixins.json
#	Fabric/build.gradle
#	build.gradle
#	gradle.properties
2025-12-23 11:51:53 +01:00
Tschipp
8d8e0dad82 Initial work on 1.21.9 2025-11-23 20:40:31 +01:00
Hanro50
e1e122ae9b Fixed crash with mannequin 2025-10-25 09:53:14 +02:00
Hanro50
69eb806228 code cleanup 2025-10-25 09:05:48 +02:00
Hanro50
08b2a41043 Fixed 3rd person rendering 2025-10-24 22:27:31 +02:00
Hanro50
6f0c20077a Update CommonEvents.java 2025-10-22 19:42:01 +02:00
Hanro50
21f09b2526 Update CommonEvents.java 2025-10-22 19:37:26 +02:00
Hanro50
9a484df16e Fixed bugs related to picking up players
- Fixed slowness getting stuck when the other player dismounted with shift
- Fixed bug where player couldn't press shift to dismount
- Fixed being unable to place other player back down
2025-10-16 07:50:31 +02:00
Hanro50
e79e52cf65 Update PickupHandler.java 2025-10-15 22:03:53 +02:00
Hanro50
d35cb4ed72 Bug fixes
- Ports fabric disconnect fix to neoforge
- Fixes console error when trying to pickup non owned tamable mobs.
2025-10-15 22:03:28 +02:00
Hanro50
5cf2e87fe8 Update CarryOnFabricMod.java 2025-10-15 21:52:23 +02:00
Hanro50
ef8362e728 Update CarryOnFabricMod.java 2025-10-15 21:51:52 +02:00
Hanro50
e3be9c84da Revert "confusing "and" and for an "or""
This reverts commit efdd3277cc.
2025-10-15 21:18:32 +02:00
Hanro50
efdd3277cc confusing "and" and for an "or" 2025-10-15 19:23:41 +02:00
Hanro50
776d079be0 forge fix 2025-10-15 09:47:48 +02:00
Hanro50
9d6ffc37ca Fixes kick on death on neoforge 2025-10-15 09:11:08 +02:00
Hanro50
af25f681be fixes the kick on respawn bug 2025-10-15 08:27:25 +02:00
Hanro50
98247bceb2 Update ClientEvents.java 2025-10-15 08:18:23 +02:00
Hanro50
41b518942d Update CarryOnRenderType.java 2025-10-15 08:16:00 +02:00
Hanro50
32db7222b7 Swear I did fix this 2025-10-15 08:07:18 +02:00
Hanro50
eadfba05e8 some mild work on porting to 1.21.9 2025-10-15 07:51:47 +02:00
ElysianCat
00c0c89858 Bump to 2.7.1: fix slot selection and AttachmentType crash
- Fixed slot selection conflict with Sounds mod that caused rapid sound spam.
- Resolved crash-on-death bug triggered by AttachmentType handling.
- Improved Carry On slot change logic for stability and compatibility.
- Updated project version from 2.7.0 → 2.7.1.
2025-09-23 23:50:26 +03:30
ElysianCat
59ecfa81e5 Merge branch 'fix/crash-on-death-1.21.8' into 1.21.8 2025-09-23 23:45:10 +03:30
ElysianCat
c4346a4c00 Refactor CarryOn functionality to improve slot selection logic. Ensure that inventory slot changes are only allowed when not carrying an item. 2025-09-23 23:43:03 +03:30
ElysianCat
3fddd1112b Add ClientboundSyncCarryDataPacket for syncing carry data and enhance carry handling on player death
- Introduced ClientboundSyncCarryDataPacket to manage carry data synchronization between server and client.
- Updated PlacementHandler to handle carry data transfer during player death scenarios, considering keepInventory game rule.
- Refactored carry data handling in CommonEvents to ensure proper transfer and clearing of carry data on player respawn.
- Registered the new packet in CarryOnCommon for clientbound communication.
2025-09-23 23:32:49 +03:30
Tschipp
ece3ed7ff2 Updated to 1.21.8. Changed Data Storage to use Attachments or Capabilities. 2025-09-01 10:18:25 +02:00
Tschipp
162fc1051d Updated to 1.21.7 2025-08-25 10:49:14 +02:00
Tschipp
e7bf9a4dee Updated to 1.21.6 2025-08-16 22:02:28 +02:00
Tschipp
7f6e41e36a Blacklisted expanded Storage 2025-07-26 09:20:45 +02:00
Texaliuz
d9d25ab598 Translation into Argentine Spanish (es_ar) for CarryOn
Hello, I would appreciate if you could add the translation to my language (es_ar) for version 1.21.1 please and thank you.
2025-07-26 00:44:24 +02:00
inceon
9b2103137f Added uk_ua.json for Ukrainian localization 2025-07-26 00:44:14 +02:00
Bayi
7fc80adfe0 Add lang **hu_hu** 2025-07-26 00:44:02 +02:00
Tschipp
c662995320 Updated Version Numbers 2025-07-26 00:39:54 +02:00
Tschipp
0dec5bb175 Fixed various Bugs 2025-07-26 00:39:32 +02:00
Tschipp
1194370405 Updated Configs 2025-07-26 00:37:35 +02:00
Tschipp
45a2b32c97 Fixed Player Carrying, closes #774 2025-07-22 23:48:52 +02:00
Tschipp
d1227d3d87 Updated to 1.21.5 2025-07-08 10:51:36 +02:00
Tschipp
60594ea3bc Updated default Blacklist 2025-04-21 23:47:53 +02:00
Tschipp
03c2b1fe1c
Merge pull request #744 from wajo21x/1.21
Added translation to Spanish (Ecuador).
2025-04-21 23:46:09 +02:00
Tschipp
43012f8462 Updated default Blacklist, Fixed Cloth Config compat with saving 2025-04-21 13:19:54 +02:00
Tschipp
24c15ffb7b Updated version, fixed 1.21.4 2025-04-20 23:40:51 +02:00
Tschipp
67db9798d8 started work on mod event hooks 2025-02-03 14:31:25 +01:00
wajo21x
a2362104fc Added translation to Spanish (Ecuador).
es_ec
2025-02-03 08:29:06 -05:00
Tschipp
5cff7411cb
Merge pull request #726 from Aresiel/patch-1
Forbid "You're in Grave Danger"'s blocks from being picked up
2025-02-02 14:08:27 +01:00
Aresiel
c803de7920
Forbid "You're in Grave Danger"'s blocks from being picked up 2025-01-07 19:55:44 +01:00
Tschipp
dd149b2472 Fixed forge server crash 2025-01-05 18:07:10 +01:00
Tschipp
ae260556b2 Updated to 1.21.4, Added support for Cloth Config 2025-01-04 00:32:09 +01:00
Tschipp
7251cbf03f Fixed crash on launch on Forge 2024-12-29 13:54:55 +01:00
Tschipp
230692baf6 Updated default Blacklist 2024-12-28 20:23:09 +01:00
Tschipp
be105218fb
Merge pull request #685 from konumatakaki/1.21
Addition of Japanese translation
2024-12-28 16:41:36 +01:00
Tschipp
58b0e8fef0
Merge pull request #701 from Hexasan/patch-1
Update Turkish Translation
2024-12-28 16:17:54 +01:00
Tschipp
93633a05bb
Merge pull request #706 from TKsMods/1.21
add german translation de_de.json
2024-12-28 16:17:06 +01:00
Tschipp
0b46e57a92
Merge pull request #678 from Tracktark/patch-1
Add minecraft:interaction to entity blacklist
2024-12-28 16:05:55 +01:00
Tschipp
1b65095902
Merge pull request #708 from NumberSir/patch-1
Create zh_cn.json
2024-12-28 13:03:27 +01:00
Tschipp
d653814af9
Merge pull request #714 from ImHoppy/ImHoppy-patch-1 2024-12-28 11:07:02 +01:00
Tschipp
38688ffb85
Merge pull request #713 from hugoalh/lang/zh_tw
Add lang `zh_tw`
2024-12-28 11:01:14 +01:00
Tschipp
058b547c30 Updated to 1.21.3 2024-12-27 18:25:03 +01:00
Hoppy
01cacce7df
Blacklist LittleTiles mod
Picking up a block from this mod can cause a crash loop due to excessive data
2024-12-01 18:14:46 +01:00
hugoalh
7ba95504a6
Add lang zh_tw 2024-11-30 17:14:43 +08:00
Number_Sir
74806d011b
Create zh_cn.json 2024-11-14 04:10:31 +08:00
Tristan Kechlo
c292eed7af add de_de.json 2024-11-07 20:49:20 +01:00
Hexasan
9b1e131641
Update Turkish Translation
-update tr_tr.json
-fixed the mistakes the other guy made
2024-11-02 23:19:09 +03:00
Konuma Takaki
5958fa43c1
Addition of Japanese translation
Japanese translation files (ja_jp.json) added
(This is a redo of #669.)
2024-09-14 14:44:26 +09:00
Tracktark
a622cf0452
Add minecraft:interaction to entity blacklist 2024-08-27 17:34:14 +02:00
Tschipp
d3ab092d4f fixed build pipeline (hopefully) 2024-08-21 09:56:53 +02:00
Tschipp
9a5b09136f changed build.gradle 2024-08-19 12:04:15 +02:00
Tschipp
8b96dab42b changed build.gradle 2024-08-19 11:27:20 +02:00
Tschipp
5271a82b9f changed build.gradle 2024-08-19 11:10:14 +02:00
Tschipp
a4843857cd Updated to 1.21.1 2024-08-19 10:58:36 +02:00
Tschipp
2a9a8703d4 fixed neoforge crashing on load 2024-07-17 23:34:36 +02:00
Tschipp
2be47d8d53 fixed fabric servers not being joinable 2024-07-17 22:31:57 +02:00
Tschipp
742a9f0ebc fixed fabric servers not being joinable 2024-07-17 22:31:36 +02:00
Tschipp
dd9964b7b2 Updated to 1.21 2024-07-14 23:57:55 +02:00
Tschipp
753f19e7b0 Updated to 1.21 2024-07-14 15:35:40 +02:00
Tschipp
3cfb59b70a
Merge pull request #647 from thatTopHatCat/patch-1
Added items from Cuffed to blacklist
2024-07-10 21:33:02 +02:00
Tschipp
02d3b110a3
Merge branch '1.20' into patch-1 2024-07-10 21:32:50 +02:00
Tschipp
2830bb3a65
Merge pull request #640 from smoong951/1.20
Update ko_kr.json
2024-07-10 21:31:36 +02:00
Tschipp
3fd4c92822 fixed build 2024-07-10 21:31:01 +02:00
Tschipp
d64aaea8f9 updated Jenkinsfile 2024-07-09 23:50:54 +02:00
Tschipp
032c1a943a updated configs 2024-07-09 23:47:22 +02:00
Wheelbarrow
43d990a4db
Added items from Cuffed to blacklist
you could pick up padlocks lmao
2024-07-07 17:54:11 -04:00
Tschipp
8cc0424d46 1.20.6 works, except for forge 2024-06-28 13:02:53 +02:00
Tschipp
b574f5b509 started work on 1.20.6 2024-06-23 20:28:08 +02:00
smoong
5750880473
Update ko_kr.json 2024-06-24 00:00:02 +09:00
Tschipp
75ca33bb8d updated Jenkinsfile 2024-02-27 22:47:33 +01:00
Tschipp
196ffb03bf updated build.gradle 2024-02-27 22:34:04 +01:00
Tschipp
08804d435d updated build.gradle, config 2024-02-27 22:14:43 +01:00
Tschipp
2f2a4a6ca5 Added proper copyright notice 2024-02-27 22:02:35 +01:00
Tschipp
5fb444a92c Fixed tags not loading, updated configs 2024-02-26 23:25:16 +01:00
Tschipp
aa6ba82ae5 Updated to 1.20.4, added NeoForge 2024-02-25 17:53:24 +01:00
Tschipp
0d9e6cf32e Fixed memory leak, crash with Rats, now compatible with newer forge versions. 2023-11-19 23:00:43 +01:00
Tschipp
be7c5e891e
Merge pull request #560 from ZEROX7/patch-1
Update mods.toml
2023-11-19 21:52:55 +01:00
ZEROX7
3ee6f8d56a
Update mods.toml
fixes not working with newer forges
2023-10-02 18:21:22 +02:00
Tschipp
dbb7e59b21 should be compatible on 1.20 2023-08-30 22:08:00 +02:00
Tschipp
68341b7ff1 Fixed various bugs relating to placement 2023-08-30 22:01:43 +02:00
Tschipp
a5366a9a2f no longer includes amecs 2023-07-25 14:08:32 +02:00
Tschipp
5efb509aea Fixed crash with amecs 2023-07-07 09:50:03 +02:00
Tschipp
ddbd9d3d84 Update to 1.20.1 2023-07-06 18:48:28 +02:00
Tschipp
e44ff0ea5b Fixed IMC, Keybinds, other bugs 2023-07-06 17:11:12 +02:00
Tschipp
0f22c9650f Merge remote-tracking branch 'origin/1.19-multiloader' into 1.19-multiloader
# Conflicts:
#	Fabric/build.gradle
2023-07-06 17:10:47 +02:00
Tschipp
5c460996ae Fixed IMC, Keybinds, other bugs 2023-07-06 17:06:47 +02:00
Tschipp
6c30e82dc5
Merge pull request #521 from alpeerkaraca/1.19-multiloader
Add tr_tr.json!
2023-07-04 19:42:57 +02:00
Alper Karaca
1d29f99e7c
Add tr_tr.json! 2023-07-04 18:55:35 +03:00
Tschipp
80899ad999
updated MixinExtras 2023-04-28 22:11:36 +02:00
Tschipp
dafcf0c0c2 Merge remote-tracking branch 'origin/1.19-multiloader' into 1.19-multiloader
# Conflicts:
#	Common/src/main/java/tschipp/carryon/common/config/CarryConfig.java
2023-04-24 22:27:25 +02:00
Tschipp
2cbff25e0c Updated to 1.19.4, fixed bugs 2023-04-24 22:24:54 +02:00
Tschipp
f330646b9d
Merge pull request #478 from Meowlala/1.19-multiloader
Config option for picking unbreakable blocks in Survival
2023-04-24 13:54:31 +02:00
Tschipp
50d47ab650
Merge pull request #469 from MarkusBordihn/patch-2
[1.19] Added easy_npc entities to the forbiddenEntities list.
2023-04-24 13:53:50 +02:00
Meowlala
a5b619a77c Config option for picking unbreakable blocks in Survival
This was supported in earlier versions of CarryOn, and has some use cases, e.g. moving BetterEnd's eternal pedestals.

Off by default, simply disables the destroySpeed check when picking up a block.

Best combined with a whitelist.
2023-03-21 11:13:40 -05:00
Markus Bordihn
b1e6ea2865
Update CarryConfig.java 2023-02-25 02:18:10 +01:00
Markus Bordihn
7cd979d3e7
Added easy_npc entities to the forbiddenEntities list. 2023-02-25 00:38:21 +01:00
Tschipp
1e1324bcde Fixed MixinExtras by using JarJar 2023-02-01 21:04:16 +01:00
Tschipp
b684df06fa
Update issue_template.md 2023-01-29 19:03:01 +01:00
Tschipp
7aacc4a524
Merge pull request #454 from Tschipp/1.19.2
Fixed shadowing of mixinextras, added french translation
2023-01-26 23:01:59 +01:00
Tschipp
edd98a10f7
Merge branch '1.19-multiloader' into 1.19.2 2023-01-26 23:01:48 +01:00
Tschipp
d8d9427e60
Merge pull request #453 from Calvineries/patch-1
Create fr_fr.json
2023-01-25 20:04:28 +01:00
Calvineries
67b114149e
Create fr_fr.json 2023-01-21 09:42:22 +01:00
Tschipp
3492b4d52b
Merge pull request #451 from Tschipp/1.19.2
Latest updates
2023-01-18 21:59:20 +01:00
Tschipp
5249002c2c
Merge branch '1.19-multiloader' into 1.19.2 2023-01-18 21:59:11 +01:00
Tschipp
6da53ee543
Merge pull request #444 from wilsontulus/patch-1
Blacklist all SecurityCraft stuff by default
2023-01-07 15:22:43 +01:00
Wilson Simanjuntak
e836734ca8
Blacklist all SecurityCraft stuff by default
Blacklist all SecurityCraft entities and blocks by default, because they're designed to be unbreakable except by their "owner(s)".
2023-01-06 13:38:45 +07:00
Tschipp
9d934e8d90
Bumped Version 2022-12-30 15:32:54 +01:00
Tschipp
b0ba88be5e
Merge pull request #442 from Tschipp/1.19.2
Added FirstPersonRender compat, augmented blacklist, fixed mixin conflict issue
2022-12-30 15:30:49 +01:00
Tschipp
209a976d4f Fixed Mixin 2022-12-17 15:51:56 +01:00
Tschipp
3c516a650f Merge remote-tracking branch 'origin/1.19-multiloader' into 1.19-multiloader 2022-12-17 15:39:20 +01:00
Tschipp
3f61e6c5a9 Updated to 1.19.3, made dependency on Gamestages less strict 2022-12-17 15:38:59 +01:00
143 changed files with 5624 additions and 1840 deletions

View File

@ -0,0 +1,22 @@
---
name: Blacklist Request
about: Have a block / entity that shouldn't be picked up by Carry On? Report it here.
title: "[Blacklist]"
labels: Blacklist
assignees: ''
---
**Describe the problem**
What block / entity is causing issues? What problems occur with placement / pickup?
**ID's to Blacklist**
List of block identifiers (namespace:name) to blacklist. You can find identifiers by activating F3 and moving your crosshair over the block
-
-
...
**Game Information (please complete the following information):**
- Minecraft Version:
- Mod Loader:
- Carry On Version:

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

@ -0,0 +1,28 @@
---
name: Bug report
about: Create a report about a crash or otherwise buggy behavior
title: "[Bug]"
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1.
2.
...
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Game Information (please complete the following information):**
- Minecraft Version:
- Mod Loader:
- Carry On Version:
**Additional context, logs**
Add any other context about the problem here. Also include logs if available

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for Carry On
title: "[Feature Request]"
labels: enhancement
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.

4
.gitignore vendored
View File

@ -21,3 +21,7 @@ build
# other
eclipse
run
runs
# vscode
.vscode/*

View File

@ -1,60 +1,51 @@
plugins {
id 'java'
id 'org.spongepowered.gradle.vanilla' version '0.2.1-SNAPSHOT'
id 'maven-publish'
}
archivesBaseName = "${mod_id}-common-${minecraft_version}"
minecraft {
version(minecraft_version)
runs {
if (project.hasProperty('common_runs_enabled') ? project.findProperty('common_runs_enabled').toBoolean() : true) {
server(project.hasProperty('common_server_run_name') ? project.findProperty('common_server_run_name') : 'vanilla_server') {
workingDirectory(this.file("run"))
}
client(project.hasProperty('common_client_run_name') ? project.findProperty('common_client_run_name') : 'vanilla_client') {
workingDirectory(this.file("run"))
}
}
}
id 'multiloader-common'
id 'net.neoforged.moddev'
}
repositories {
maven {
name = "Shedaniel"
url "https://maven.shedaniel.me/"
}
maven { url 'https://jitpack.io' }
}
neoForge {
neoFormVersion = neo_form_version
// Automatically enable AccessTransformers if the file exists
def at = file('src/main/resources/META-INF/accesstransformer.cfg')
if (at.exists()) {
accessTransformers.from(at.absolutePath)
}
parchment {
minecraftVersion = parchment_game_version
mappingsVersion = parchment_version
}
}
dependencies {
compileOnly group:'org.spongepowered', name:'mixin', version:'0.8.5'
implementation group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1'
implementation("com.github.LlamaLad7:MixinExtras:${mixinextras_version}")
annotationProcessor("com.github.LlamaLad7:MixinExtras:${mixinextras_version}")
compileOnly group: 'org.spongepowered', name: 'mixin', version: '0.8.5'
// fabric and neoforge both bundle mixinextras, so it is safe to use it in common
implementation("io.github.llamalad7:mixinextras-common:${mixinextras_version}")
annotationProcessor("io.github.llamalad7:mixinextras-common:${mixinextras_version}")
compileOnly("me.shedaniel.cloth:cloth-config-neoforge:${cloth_config_version}")
}
processResources {
def buildProps = project.properties.clone()
filesMatching(['pack.mcmeta']) {
expand buildProps
configurations {
commonJava {
canBeResolved = false
canBeConsumed = true
}
commonResources {
canBeResolved = false
canBeConsumed = true
}
}
publishing {
publications {
mavenJava(MavenPublication) {
groupId project.group
artifactId project.archivesBaseName
version project.version
from components.java
}
}
repositories {
maven {
url "file://" + System.getenv("local_maven")
}
}
artifacts {
commonJava sourceSets.main.java.sourceDirectories.singleFile
commonResources sourceSets.main.resources.sourceDirectories.singleFile
}

View File

@ -1,10 +1,32 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
@ -15,6 +37,7 @@ import tschipp.carryon.common.carry.CarryOnDataManager;
import tschipp.carryon.common.carry.PlacementHandler;
import tschipp.carryon.common.command.CommandCarryOn;
import tschipp.carryon.config.ConfigLoader;
import tschipp.carryon.networking.clientbound.ClientboundStartRidingOtherPlayerPacket;
import tschipp.carryon.networking.clientbound.ClientboundStartRidingPacket;
import tschipp.carryon.networking.clientbound.ClientboundSyncScriptsPacket;
import tschipp.carryon.networking.serverbound.ServerboundCarryKeyPressedPacket;
@ -22,36 +45,49 @@ import tschipp.carryon.platform.Services;
public class CarryOnCommon
{
public static void registerServerPackets()
public static final RegistrySetBuilder BUILDER = new RegistrySetBuilder();
public static HolderLookup.Provider createLookup() {
RegistryAccess.Frozen registryaccess$frozen = RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY);
HolderLookup.Provider holderlookup$provider = BUILDER.build(registryaccess$frozen);
return holderlookup$provider;
}
public static void registerServerPackets(Object... args)
{
Services.PLATFORM.registerServerboundPacket(
Constants.PACKET_ID_KEY_PRESSED,
0,
ServerboundCarryKeyPressedPacket.TYPE,
ServerboundCarryKeyPressedPacket.class,
ServerboundCarryKeyPressedPacket::toBytes,
ServerboundCarryKeyPressedPacket::new,
ServerboundCarryKeyPressedPacket::handle
ServerboundCarryKeyPressedPacket.CODEC,
ServerboundCarryKeyPressedPacket::handle,
args
);
}
public static void registerClientPackets()
public static void registerClientPackets(Object... args)
{
Services.PLATFORM.registerClientboundPacket(
Constants.PACKET_ID_START_RIDING,
1,
ClientboundStartRidingPacket.TYPE,
ClientboundStartRidingPacket.class,
ClientboundStartRidingPacket::toBytes,
ClientboundStartRidingPacket::new,
ClientboundStartRidingPacket::handle
ClientboundStartRidingPacket.CODEC,
ClientboundStartRidingPacket::handle,
args
);
Services.PLATFORM.registerClientboundPacket(
Constants.PACKET_ID_SYNC_SCRIPTS,
2,
ClientboundSyncScriptsPacket.TYPE,
ClientboundSyncScriptsPacket.class,
ClientboundSyncScriptsPacket::toBytes,
ClientboundSyncScriptsPacket::new,
ClientboundSyncScriptsPacket::handle
ClientboundSyncScriptsPacket.CODEC,
ClientboundSyncScriptsPacket::handle,
args
);
Services.PLATFORM.registerClientboundPacket(
ClientboundStartRidingOtherPlayerPacket.TYPE,
ClientboundStartRidingOtherPlayerPacket.class,
ClientboundStartRidingOtherPlayerPacket.CODEC,
ClientboundStartRidingOtherPlayerPacket::handle,
args
);
}
@ -72,20 +108,19 @@ public class CarryOnCommon
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if(carry.isCarrying())
{
// Dumb Fix to sync Carry Data after a respawn with KeepInventory, because we can't sync in the first tick.
if(player.tickCount == 1)
CarryOnDataManager.setCarryData(player, carry);
if(carry.getActiveScript().isPresent())
{
String cmd = carry.getActiveScript().get().scriptEffects().commandLoop();
if(!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
player.level().getServer().getCommands().performPrefixedCommand(player.level().getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().name() + " run " + cmd);
}
if (!Constants.COMMON_CONFIG.settings.slownessInCreative && player.isCreative())
return;
player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 1, potionLevel(carry, player.level), false, false));
Inventory inv = player.getInventory();
inv.selected = carry.getSelected();
inv.setSelectedSlot(carry.getSelected());
}
}
@ -119,7 +154,7 @@ public class CarryOnCommon
public static void onPlayerAttacked(Player player)
{
if (Constants.COMMON_CONFIG.settings.dropCarriedWhenHit && !player.level.isClientSide)
if (Constants.COMMON_CONFIG.settings.dropCarriedWhenHit && !player.level().isClientSide())
{
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if (carry.isCarrying())
@ -130,8 +165,18 @@ public class CarryOnCommon
}
}
public static void onRiderDisconnected(Player rider)
{
if(rider.getVehicle() instanceof ServerPlayer vehicle) {
CarryOnData data = CarryOnDataManager.getCarryData(vehicle);
if(data.isCarrying(CarryType.PLAYER)) {
PlacementHandler.placeCarried(vehicle);
}
}
}
private static int potionLevel(CarryOnData carry, Level level)
public static int potionLevel(CarryOnData carry, Level level)
{
if(carry.isCarrying(CarryType.PLAYER))
return 1;

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon;
import net.minecraft.client.Minecraft;
@ -14,11 +34,11 @@ public class CarryOnCommonClient
Player player = mc.player;
if(player != null) {
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if ((CarryOnKeybinds.carryKey.isUnbound() ? player.isShiftKeyDown() : CarryOnKeybinds.carryKey.isDown()) && !carry.isKeyPressed()) {
if ((CarryOnKeybinds.carryKey.isUnbound() ? player.isShiftKeyDown() : (CarryOnKeybinds.carryKey.isDown())) && !carry.isKeyPressed()) {
CarryOnKeybinds.onCarryKey(true);
carry.setKeyPressed(true);
CarryOnDataManager.setCarryData(player, carry);
} else if (!(CarryOnKeybinds.carryKey.isUnbound() ? player.isShiftKeyDown() : CarryOnKeybinds.carryKey.isDown()) && carry.isKeyPressed()) {
} else if (!(CarryOnKeybinds.carryKey.isUnbound() ? player.isShiftKeyDown() : (CarryOnKeybinds.carryKey.isDown() ) ) && carry.isKeyPressed()) {
CarryOnKeybinds.onCarryKey(false);
carry.setKeyPressed(false);
CarryOnDataManager.setCarryData(player, carry);
@ -26,14 +46,16 @@ public class CarryOnCommonClient
}
}
public static void onCarryClientTick()
{
public static void onCarryClientTick() {
Player player = Minecraft.getInstance().player;
if(player != null) {
if (player != null) {
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if(carry.isCarrying())
{
player.getInventory().selected = carry.getSelected();
if (carry.isCarrying()) {
int wantedSlot = carry.getSelected();
if (player.getInventory().getSelectedSlot() != wantedSlot) {
player.getInventory().setSelectedSlot(wantedSlot);
}
}
}
}
@ -42,4 +64,4 @@ public class CarryOnCommonClient
{
return Minecraft.getInstance().player;
}
}
}

View File

@ -1,6 +1,26 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tschipp.carryon.common.config.CarryConfig;
@ -14,8 +34,10 @@ public class Constants {
public static final CarryConfig.Common COMMON_CONFIG = new CarryConfig.Common();
public static final CarryConfig.Client CLIENT_CONFIG = new CarryConfig.Client();
public static final ResourceLocation PACKET_ID_KEY_PRESSED = new ResourceLocation(Constants.MOD_ID, "key_pressed");
public static final ResourceLocation PACKET_ID_START_RIDING = new ResourceLocation(Constants.MOD_ID, "start_riding");
public static final ResourceLocation PACKET_ID_SYNC_SCRIPTS = new ResourceLocation(Constants.MOD_ID, "sync_scripts");
public static final Identifier PACKET_ID_KEY_PRESSED = Identifier.fromNamespaceAndPath(Constants.MOD_ID, "key_pressed");
public static final Identifier PACKET_ID_START_RIDING = Identifier.fromNamespaceAndPath(Constants.MOD_ID, "start_riding");
public static final Identifier PACKET_ID_SYNC_SCRIPTS = Identifier.fromNamespaceAndPath(Constants.MOD_ID, "sync_scripts");
public static final Identifier PACKET_ID_START_RIDING_OTHER = Identifier.fromNamespaceAndPath(Constants.MOD_ID, "start_riding_other");
public static final Identifier PACKET_ID_SYNC_CARRY_ON_DATA = Identifier.fromNamespaceAndPath(Constants.MOD_ID, "sync_carry_data");
}

View File

@ -1,7 +1,29 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.client.keybinds;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.KeyMapping.Category;
import net.minecraft.resources.Identifier;
import tschipp.carryon.Constants;
import tschipp.carryon.networking.serverbound.ServerboundCarryKeyPressedPacket;
import tschipp.carryon.platform.Services;
@ -14,7 +36,10 @@ public class CarryOnKeybinds
public static void registerKeybinds(Consumer<KeyMapping> registrar)
{
carryKey = new ConflictFreeKeyMapping("key.carry.desc", Services.PLATFORM.getPlatformName().equals("Forge") ? InputConstants.KEY_LSHIFT : InputConstants.UNKNOWN.getValue(), "key.carry.category");
Category category = Category.register(Identifier.fromNamespaceAndPath(Constants.MOD_ID,"key.carry.category"));
carryKey = new KeyMapping("key.carry.desc", InputConstants.KEY_LSHIFT, category);
registrar.accept(carryKey);
}

View File

@ -1,23 +0,0 @@
package tschipp.carryon.client.keybinds;
import com.mojang.blaze3d.platform.InputConstants.Type;
import net.minecraft.client.KeyMapping;
public class ConflictFreeKeyMapping extends KeyMapping
{
public ConflictFreeKeyMapping(String $$0, int $$1, String $$2)
{
super($$0, $$1, $$2);
}
public ConflictFreeKeyMapping(String $$0, Type $$1, int $$2, String $$3)
{
super($$0, $$1, $$2, $$3);
}
@Override
public boolean same(KeyMapping $$0)
{
return false;
}
}

View File

@ -1,16 +1,35 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.client.modeloverride;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import net.minecraft.commands.arguments.blocks.BlockStateParser;
import net.minecraft.commands.arguments.blocks.BlockStateParser.BlockResult;
import net.minecraft.commands.arguments.item.ItemParser;
import net.minecraft.commands.arguments.item.ItemParser.ItemResult;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
@ -20,27 +39,18 @@ import tschipp.carryon.common.scripting.Matchables.NBTCondition;
import javax.annotation.Nullable;
import java.util.Map;
public class ModelOverride
{
public static Codec<ModelOverride> CODEC = Codec.STRING.comapFlatMap(ModelOverride::of, override -> override.raw);
private String raw;
public class ModelOverride {
private BlockResult parsedBlock;
private Type type;
private Either<ItemResult, BlockResult> parsedRHS;
private Either<ItemStack, BlockState> renderObject;
private ModelOverride(String raw, BlockResult parsedBlock, Type type, Either<ItemResult, BlockResult> parsedRHS)
{
this.raw = raw;
this.parsedBlock = parsedBlock;
this.type = type;
this.parsedRHS = parsedRHS;
parsedRHS.ifLeft(res -> {
ItemStack stack = new ItemStack(res.item());
if(res.nbt() != null)
stack.setTag(res.nbt());
if(res.components() != null)
stack.applyComponents(res.components());
this.renderObject = Either.left(stack);
});
@ -50,10 +60,10 @@ public class ModelOverride
});
}
public static DataResult<ModelOverride> of(String str)
public static DataResult<ModelOverride> of(String str, HolderLookup.Provider provider)
{
if(!str.contains("->"))
return DataResult.error(str + " must contain -> Arrow!");
return DataResult.error(() -> str + " must contain -> Arrow!");
String[] split = str.split("->");
String from = split[0];
String to = split[1];
@ -61,9 +71,9 @@ public class ModelOverride
BlockResult res;
try {
res = BlockStateParser.parseForBlock(Registry.BLOCK, from, true);
} catch (CommandSyntaxException e) {
return DataResult.error("Error while parsing " + from + ":" + e.getMessage());
res = BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK, from, true);
} catch (Exception e) {
return DataResult.error(() -> "Error while parsing " + from + ":" + e.getMessage());
}
Type type = Type.ITEM;
@ -79,11 +89,12 @@ public class ModelOverride
Either<ItemResult, BlockResult> either;
try {
if(type == Type.ITEM)
either = Either.left(ItemParser.parseForItem(HolderLookup.forRegistry(Registry.ITEM), new StringReader(to)));
either = Either.left(new ItemParser(provider).parse(new StringReader(to)));
else
either = Either.right(BlockStateParser.parseForBlock(Registry.BLOCK, to, true));
either = Either.right(BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK, to, true));
}catch (CommandSyntaxException e) {
return DataResult.error("Error while parsing " + to + ":" + e.getMessage());
String finalTo = to;
return DataResult.error(() -> "Error while parsing " + finalTo + ":" + e.getMessage());
}
return DataResult.success(new ModelOverride(str, res, type, either));

View File

@ -1,6 +1,27 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.client.modeloverride;
import com.mojang.serialization.DataResult;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;
import tschipp.carryon.Constants;
@ -14,13 +35,13 @@ public class ModelOverrideHandler
{
private static List<ModelOverride> OVERRIDES = new ArrayList<>();
public static void initModelOverrides()
public static void initModelOverrides(HolderLookup.Provider provider)
{
OVERRIDES.clear();
for(String ov : Constants.CLIENT_CONFIG.modelOverrides)
{
addFromString(ov);
addFromString(ov, provider);
}
}
@ -34,9 +55,9 @@ public class ModelOverrideHandler
return Optional.empty();
}
public static void addFromString(String str)
public static void addFromString(String str, HolderLookup.Provider provider)
{
DataResult<ModelOverride> res = ModelOverride.of(str);
DataResult<ModelOverride> res = ModelOverride.of(str, provider);
if(res.result().isPresent())
{
ModelOverride override = res.result().get();

View File

@ -1,47 +1,61 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.client.render;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.math.Vector3f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.MultiBufferSource.BufferSource;
import net.minecraft.client.renderer.SubmitNodeCollector;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.renderer.rendertype.RenderTypes;
import net.minecraft.client.renderer.state.CameraRenderState;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import tschipp.carryon.Constants;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.common.carry.CarryOnData.CarryType;
import tschipp.carryon.common.carry.CarryOnDataManager;
import tschipp.carryon.common.scripting.CarryOnScript;
import tschipp.carryon.common.scripting.CarryOnScript.ScriptRender;
import tschipp.carryon.platform.Services;
import java.util.Optional;
public class CarriedObjectRender
{
public static boolean drawFirstPerson(Player player, MultiBufferSource buffer, PoseStack matrix, int light, float partialTicks)
public static boolean draw(Player player, PoseStack matrix, int light, float partialTicks,SubmitNodeCollector nodeCollector, boolean firstPerson)
{
if(Services.PLATFORM.isModLoaded("firstperson") || Services.PLATFORM.isModLoaded("firstpersonmod"))
if(Services.PLATFORM.isModLoaded("firstperson") || Services.PLATFORM.isModLoaded("firstpersonmod") || player == null)
return false;
CarryOnData carry = CarryOnDataManager.getCarryData(player);
try {
if (carry.isCarrying(CarryType.BLOCK))
drawFirstPersonBlock(player, buffer, matrix, light, CarryRenderHelper.getRenderState(player));
drawBlock(player, matrix, light, CarryRenderHelper.getRenderState(player), nodeCollector, firstPerson, partialTicks);
else if (carry.isCarrying(CarryType.ENTITY))
drawFirstPersonEntity(player, buffer, matrix, light, partialTicks);
drawEntity(player, matrix, light, partialTicks, nodeCollector, firstPerson);
}
catch (Exception e)
{
@ -61,178 +75,59 @@ public class CarriedObjectRender
return carry.isCarrying();
}
private static void drawFirstPersonBlock(Player player, MultiBufferSource buffer, PoseStack matrix, int light, BlockState state)
private static void drawBlock(Player player, PoseStack matrix, int light, BlockState state, SubmitNodeCollector nodeCollector, boolean firstPerson, float partialTicks)
{
matrix.pushPose();
matrix.scale(2.5f, 2.5f, 2.5f);
matrix.translate(0, -0.5, -1);
RenderSystem.enableBlend();
RenderSystem.disableCull();
CarryOnData carry = CarryOnDataManager.getCarryData(player);
ItemStackRenderState renderState = new ItemStackRenderState();
var layer = renderState.newLayer();
layer.setRenderType(RenderTypes.glint());
if (Constants.CLIENT_CONFIG.facePlayer != CarryRenderHelper.isChest(state.getBlock())) {
matrix.mulPose(Vector3f.YP.rotationDegrees(180));
matrix.mulPose(Vector3f.XN.rotationDegrees(8));
} else {
matrix.mulPose(Vector3f.XP.rotationDegrees(8));
}
matrix.pushPose();
if(carry.getActiveScript().isPresent())
CarryRenderHelper.performScriptTransformation(matrix, carry.getActiveScript().get());
PoseStack renderPose = CarryRenderHelper.setupBlockTransformations(player, matrix, carry, firstPerson);
RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);
ItemStack stack = new ItemStack(state.getBlock().asItem());
BakedModel model = CarryRenderHelper.getRenderBlock(player);
CarryRenderHelper.renderBakedModel(stack, matrix, buffer, light, model);
RenderSystem.enableCull();
RenderSystem.disableBlend();
ItemStack renderStack = CarryRenderHelper.getRenderItemStack(player);
Minecraft.getInstance().getItemModelResolver().updateForTopItem(renderState, renderStack, ItemDisplayContext.NONE, player.level(), null, 0);
renderState.submit(renderPose, nodeCollector, light, OverlayTexture.NO_OVERLAY, 0);
matrix.popPose();
}
private static void drawFirstPersonEntity(Player player, MultiBufferSource buffer, PoseStack matrix, int light, float partialTicks) {
private static void drawEntity(Player player, PoseStack matrix, int light, float partialTicks,SubmitNodeCollector nodeCollector, boolean firstPerson) {
EntityRenderDispatcher manager = Minecraft.getInstance().getEntityRenderDispatcher();
Entity entity = CarryRenderHelper.getRenderEntity(player);
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if (entity != null)
{
Vec3 playerpos = CarryRenderHelper.getExactPos(player, partialTicks);
if (entity == null)
return;
entity.setPos(playerpos.x, playerpos.y, playerpos.z);
entity.xRotO = 0.0f;
entity.yRotO = 0.0f;
entity.setYHeadRot(0.0f);
Vec3 playerpos = CarryRenderHelper.getExactPos(player, partialTicks);
float height = entity.getBbHeight();
float width = entity.getBbWidth();
entity.setPos(playerpos.x, playerpos.y, playerpos.z);
entity.xRotO = 0.0f;
entity.yRotO = 0.0f;
entity.setYHeadRot(0.0f);
matrix.pushPose();
matrix.scale(0.8f, 0.8f, 0.8f);
matrix.mulPose(Vector3f.YP.rotationDegrees(180));
matrix.translate(0.0, -height - .1, width + 0.1);
matrix.pushPose();
manager.setRenderShadow(false);
CarryRenderHelper.setupEntityTransformations(player, matrix, carry, firstPerson);
Optional<CarryOnScript> res = carry.getActiveScript();
if(res.isPresent())
{
CarryOnScript script = res.get();
CarryRenderHelper.performScriptTransformation(matrix, script);
}
if (entity instanceof LivingEntity)
((LivingEntity) entity).hurtTime = 0;
if (entity instanceof LivingEntity)
((LivingEntity) entity).hurtTime = 0;
try {
manager.render(entity, 0, 0, 0, 0f, 0, matrix, buffer, light);
}
catch (Exception e)
{
}
manager.setRenderShadow(true);
}
// RenderSystem.disableAlphaTest();
matrix.popPose();
}
/**
* Draws the third person view of entities and blocks
* @param partialticks
* @param matrix
*/
public static void drawThirdPerson(float partialticks, PoseStack matrix) {
Minecraft mc = Minecraft.getInstance();
Level level = mc.level;
BufferSource buffer = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());
int light = 0;
int perspective = CarryRenderHelper.getPerspective();
EntityRenderDispatcher manager = mc.getEntityRenderDispatcher();
RenderSystem.enableBlend();
RenderSystem.disableCull();
RenderSystem.disableDepthTest();
for (Player player : level.players())
{
try {
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if (perspective == 0 && player == mc.player && !(Services.PLATFORM.isModLoaded("firstperson") || Services.PLATFORM.isModLoaded("firstpersonmod")))
continue;
light = manager.getPackedLightCoords(player, partialticks);
if (carry.isCarrying(CarryType.BLOCK)) {
BlockState state = CarryRenderHelper.getRenderState(player);
CarryRenderHelper.applyBlockTransformations(player, partialticks, matrix, state.getBlock());
ItemStack tileItem = new ItemStack(state.getBlock().asItem());
BakedModel model = CarryRenderHelper.getRenderBlock(player);
//ModelOverridesHandler.hasCustomOverrideModel(state, tag) ? ModelOverridesHandler.getCustomOverrideModel(state, tag, level, player) : tileItem.isEmpty() ? mc.getBlockRenderer().getBlockModel(state) : mc.getItemRenderer().getModel(tileItem, level, player, 0);
//
Optional<CarryOnScript> res = carry.getActiveScript();
if (res.isPresent()) {
CarryOnScript script = res.get();
CarryRenderHelper.performScriptTransformation(matrix, script);
}
RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);
RenderSystem.enableCull();
PoseStack.Pose p = matrix.last();
PoseStack copy = new PoseStack();
copy.mulPoseMatrix(p.pose());
matrix.popPose();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
CarryRenderHelper.renderBakedModel(tileItem, copy, buffer, light, model);
buffer.endBatch();
matrix.popPose();
} else if (carry.isCarrying(CarryType.ENTITY)) {
Entity entity = CarryRenderHelper.getRenderEntity(player);
if (entity != null) {
CarryRenderHelper.applyEntityTransformations(player, partialticks, matrix, entity);
manager.setRenderShadow(false);
Optional<CarryOnScript> res = carry.getActiveScript();
if (res.isPresent()) {
CarryOnScript script = res.get();
CarryRenderHelper.performScriptTransformation(matrix, script);
}
if (entity instanceof LivingEntity le)
le.hurtTime = 0;
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
manager.render(entity, 0, 0, 0, 0f, 0, matrix, buffer, light);
buffer.endBatch();
matrix.popPose();
manager.setRenderShadow(true);
matrix.popPose();
}
}
}
catch (Exception e)
{
}
}
RenderSystem.enableDepthTest();
RenderSystem.enableCull();
RenderSystem.disableBlend();
}
try {
EntityRenderState renderState = manager.extractEntity(entity, 0);
renderState.shadowPieces.clear();
renderState.lightCoords = light;
manager.submit(renderState, new CameraRenderState(), 0, 0, 0, matrix, nodeCollector);
}
catch (Exception ignored)
{
}
matrix.popPose();
if(!firstPerson)
matrix.popPose();
}
}

View File

@ -1,30 +1,45 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.client.render;
import com.mojang.authlib.minecraft.client.MinecraftClient;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import com.mojang.math.Axis;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Registry;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.joml.Quaternionf;
import tschipp.carryon.Constants;
import tschipp.carryon.client.modeloverride.ModelOverride;
import tschipp.carryon.client.modeloverride.ModelOverrideHandler;
@ -54,159 +69,139 @@ public class CarryRenderHelper
return -(entity.yBodyRotO + (entity.yBodyRot - entity.yBodyRotO) * partialticks);
}
public static Quaternion getExactBodyRotation(LivingEntity entity, float partialticks)
public static Quaternionf getExactBodyRotation(LivingEntity entity, float partialticks)
{
return Vector3f.YP.rotationDegrees(getExactBodyRotationDegrees(entity, partialticks));
return Axis.YP.rotationDegrees(getExactBodyRotationDegrees(entity, partialticks));
}
public static void applyGeneralTransformations(Player player, float partialticks, PoseStack matrix)
public static void applyGeneralTransformations(Player player, PoseStack matrix)
{
int perspective = CarryRenderHelper.getPerspective();
Quaternion playerrot = CarryRenderHelper.getExactBodyRotation(player, partialticks);
Vec3 playerpos = CarryRenderHelper.getExactPos(player, partialticks);
Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
Vec3 offset = playerpos.subtract(cameraPos);
Pose pose = player.getPose();
matrix.pushPose();
matrix.translate(offset.x, offset.y, offset.z);
if (perspective == 2)
playerrot.mul(Vector3f.YP.rotationDegrees(180));
matrix.mulPose(playerrot);
matrix.pushPose();
matrix.scale(0.6f, 0.6f, 0.6f);
if (perspective == 2)
matrix.translate(0, 0, -1.35);
matrix.translate(0, 0, -1.35);
if (doSneakCheck(player))
{
matrix.translate(0, -0.4, 0);
}
if (pose == Pose.SWIMMING)
if (pose == Pose.SWIMMING || pose == Pose.FALL_FLYING)
{
float f = player.getSwimAmount(partialticks);
float f3 = player.isInWater() ? -90.0F - player.xRotO : -90.0F;
float f4 = Mth.lerp(f, 0.0F, f3);
if (perspective == 2)
{
matrix.translate(0, 0, 1.35);
matrix.mulPose(Vector3f.XP.rotationDegrees(f4));
}
else
matrix.mulPose(Vector3f.XN.rotationDegrees(f4));
matrix.translate(0, -1.5, -1.848);
if (perspective == 2)
matrix.translate(0, 0, 2.38);
matrix.translate(0, 0, 2.5);
matrix.mulPose(Axis.XP.rotationDegrees(90));
}
if (pose == Pose.FALL_FLYING)
{
float f1 = player.getFallFlyingTicks() + partialticks;
float f2 = Mth.clamp(f1 * f1 / 100.0F, 0.0F, 1.0F);
if (!player.isAutoSpinAttack())
{
if (perspective == 2)
matrix.translate(0, 0, 1.35);
if (perspective == 2)
matrix.mulPose(Vector3f.XP.rotationDegrees(f2 * (-90.0F - player.xRotO)));
else
matrix.mulPose(Vector3f.XN.rotationDegrees(f2 * (-90.0F - player.xRotO)));
}
Vec3 viewVector = player.getViewVector(partialticks);
Vec3 deltaMovement = player.getDeltaMovement();
double d0 = deltaMovement.horizontalDistanceSqr();
double d1 = deltaMovement.horizontalDistanceSqr();
if (d0 > 0.0D && d1 > 0.0D)
{
double d2 = (deltaMovement.x * viewVector.x + deltaMovement.z * viewVector.z) / (Math.sqrt(d0) * Math.sqrt(d1));
double d3 = deltaMovement.x * viewVector.z - deltaMovement.z * viewVector.x;
matrix.mulPose(Vector3f.YP.rotation((float) (Math.signum(d3) * Math.acos(d2))));
}
if (perspective != 2)
matrix.translate(0, 0, -1.35);
matrix.translate(0, -0.2, 0);
}
matrix.translate(0, 1.6, 0.65);
matrix.translate(0, -0.5, 0.65);
}
public static void applyBlockTransformations(Player player, float partialticks, PoseStack matrix, Block block)
{
int perspective = CarryRenderHelper.getPerspective();
public static PoseStack setupBlockTransformations(Player player, PoseStack matrix, CarryOnData carry, boolean firstPerson) {
if (firstPerson) {
matrix.scale(2.5f, 2.5f, 2.5f);
matrix.translate(0, -0.5, -1);
applyGeneralTransformations(player, partialticks, matrix);
if (Constants.CLIENT_CONFIG.facePlayer != CarryRenderHelper.isChest(carry.getBlock().getBlock())) {
matrix.mulPose(Axis.YP.rotationDegrees(180));
matrix.mulPose(Axis.XN.rotationDegrees(8));
} else {
matrix.mulPose(Axis.XP.rotationDegrees(8));
}
carry.getActiveScript().ifPresent(script -> CarryRenderHelper.performScriptTransformation(matrix, script));
return matrix;
} else {
CarryRenderHelper.applyBlockTransformations(player, matrix, carry.getBlock().getBlock());
carry.getActiveScript().ifPresent(script -> CarryRenderHelper.performScriptTransformation(matrix, script));
PoseStack.Pose p = matrix.last();
PoseStack copy = new PoseStack();
copy.mulPose(p.pose());
matrix.popPose();
return copy;
}
}
public static void applyBlockTransformations(Player player, PoseStack matrix, Block block)
{
matrix.mulPose(Axis.ZN.rotationDegrees(180));
applyGeneralTransformations(player, matrix);
if (Constants.CLIENT_CONFIG.facePlayer != CarryRenderHelper.isChest(block))
{
//TODO: RealFirstPersonRender
//if ((ModList.get().isLoaded("realrender") || ModList.get().isLoaded("rfpr")) && perspective == 0)
// matrix.translate(0, 0, -0.4);
matrix.mulPose(Vector3f.YP.rotationDegrees(180));
matrix.mulPose(Axis.YP.rotationDegrees(180));
}
// if(perspective == 1)
// {
// matrix.pushPose();
// //matrix.mulPose(Vector3f.YP.rotationDegrees(180));
// matrix.popPose();
// }
//else if ((ModList.get().isLoaded("realrender") || ModList.get().isLoaded("rfpr")) && perspective == 0)
// matrix.translate(0, 0, 0.4);
//matrix.mulPose(Vector3f.YP.rotationDegrees(180));
float height = getRenderHeight(player);
float offset = (height - 1f) / 1.2f;
matrix.translate(0, -offset, 0);
}
public static void applyEntityTransformations(Player player, float partialticks, PoseStack matrix, Entity entity)
public static void setupEntityTransformations(Player player, PoseStack matrix, CarryOnData carry, boolean firstPerson) {
Entity entity = carry.getEntity(player.level());
float height = entity.getBbHeight();
float width = entity.getBbWidth();
if(firstPerson) {
matrix.mulPose(Axis.YP.rotationDegrees(180));
matrix.scale(0.8f, 0.8f, 0.8f);
matrix.translate(0.0, -height - .2, width * 1.3 + 0.1);
carry.getActiveScript().ifPresent(script -> CarryRenderHelper.performScriptTransformation(matrix, script));
if(Constants.CLIENT_CONFIG.rotateEntitiesSideways)
matrix.mulPose(Axis.YP.rotationDegrees(90));
}
else {
applyEntityTransformations(player, matrix, entity);
carry.getActiveScript().ifPresent(script -> CarryRenderHelper.performScriptTransformation(matrix, script));
}
}
public static void applyEntityTransformations(Player player, PoseStack matrix, Entity entity)
{
int perspective = CarryRenderHelper.getPerspective();
Pose pose = player.getPose();
applyGeneralTransformations(player, partialticks, matrix);
applyGeneralTransformations(player, matrix);
if (perspective == 2)
matrix.translate(0, -1.6, 0.65);
else
matrix.translate(0, -1.6, -0.65);
matrix.mulPose(Axis.XP.rotationDegrees(180));
matrix.translate(0, -3.1, -0.65);
matrix.scale(1.666f, 1.666f, 1.666f);
float height = entity.getBbHeight();
float width = entity.getBbWidth();
float multiplier = height * width;
float multiplier = Math.min(9.9f, height * width) ;
entity.yo = 0.0f;
entity.yRotO = 0.0f;
entity.setYHeadRot(0.0f);
entity.xo = 0.0f;
entity.xRotO = 0.0f;
if (perspective == 2)
matrix.mulPose(Vector3f.YP.rotationDegrees(180));
matrix.scale((10 - multiplier) * 0.08f, (10 - multiplier) * 0.08f, (10 - multiplier) * 0.08f);
matrix.translate(0.0, height / 2 + -(height / 2) + 1, width - 0.1 < 0.7 ? width - 0.1 + (0.7 - (width - 0.1)) : width - 0.1);
matrix.translate(0.0, height / 2 + -(height / 4) + 1, width - 0.1 < 0.7 ? width - 0.1 + (0.7 - (width - 0.1)) : width - 0.1);
if(doSneakCheck(player))
matrix.translate(0, -0.4, 0);
if (pose == Pose.SWIMMING || pose == Pose.FALL_FLYING)
{
matrix.mulPose(Vector3f.XN.rotationDegrees(90));
matrix.translate(0, -0.2 * height, 0);
if (pose == Pose.FALL_FLYING)
matrix.translate(0, 0, 0.2);
matrix.mulPose(Axis.XN.rotationDegrees(180));
matrix.translate(0, 0.2 * height - 2, -0.5);
}
if(Constants.CLIENT_CONFIG.rotateEntitiesSideways)
matrix.mulPose(Axis.YP.rotationDegrees(90));
}
@ -220,9 +215,9 @@ public class CarryRenderHelper
Vec3 rotation = render.renderRotation().getVec();
Vec3 scale = render.renderscale().getVec(1, 1, 1);
Quaternion rot = Vector3f.XP.rotationDegrees((float) rotation.x);
rot.mul(Vector3f.YP.rotationDegrees((float) rotation.y));
rot.mul(Vector3f.ZP.rotationDegrees((float) rotation.z));
Quaternionf rot = Axis.XP.rotationDegrees((float) rotation.x);
rot.mul(Axis.YP.rotationDegrees((float) rotation.y));
rot.mul(Axis.ZP.rotationDegrees((float) rotation.z));
matrix.mulPose(rot);
matrix.translate(translation.x, translation.y, perspective == 1 && script.isBlock() ? -translation.z : translation.z);
@ -230,18 +225,64 @@ public class CarryRenderHelper
matrix.scale((float) scale.x, (float) scale.y, (float) scale.z);
}
/*
@Deprecated
public static void renderBakedModel(ItemStack stack, PoseStack matrix, MultiBufferSource buffer, int light, BakedModel model)
{
ItemStackRenderState state = new ItemStackRenderState();
try {
ItemStackRenderState.LayerRenderState layer = state.newLayer();
if(stack.hasFoil())
layer.setFoilType(ItemStackRenderState.FoilType.STANDARD);
layer.setupBlockModel(model, RenderType.translucent());
state.render(matrix, buffer, light, OverlayTexture.NO_OVERLAY);
ItemRenderer renderer = Minecraft.getInstance().getItemRenderer();
renderer.render(stack, TransformType.NONE, false, matrix, buffer, light, OverlayTexture.NO_OVERLAY, model);
renderer.renderStatic(stack, ItemDisplayContext.NONE, light, OverlayTexture.NO_OVERLAY, matrix, buffer, null, model, 0);
renderer.render(stack, ItemDisplayContext.NONE, false, matrix, buffer, light, OverlayTexture.NO_OVERLAY, model);
}
catch (Exception e)
{
}
}
*/
public static ItemStack getRenderItemStack(Player player)
{
CarryOnData carry = CarryOnDataManager.getCarryData(player);
BlockState state = carry.getBlock().getBlock().defaultBlockState();
if(carry.getActiveScript().isPresent())
{
ScriptRender render = carry.getActiveScript().get().scriptRender();
if(render.renderNameBlock().isPresent())
{
state = BuiltInRegistries.BLOCK.get(render.renderNameBlock().get()).get().value().defaultBlockState();
}
}
ItemStack renderStack = ItemStack.EMPTY;
Optional<ModelOverride> ov = ModelOverrideHandler.getModelOverride(state, carry.getContentNbt());
if(ov.isPresent())
{
var renderObj = ov.get().getRenderObject();
if(renderObj.right().isPresent())
state = renderObj.right().get();
else if (renderObj.left().isPresent())
renderStack = renderObj.left().get();
}
if(renderStack.isEmpty())
renderStack = new ItemStack(state.getBlock());
return renderStack;
}
public static BlockState getRenderState(Player player)
{
@ -251,7 +292,9 @@ public class CarryRenderHelper
{
ScriptRender render = carry.getActiveScript().get().scriptRender();
if(render.renderNameBlock().isPresent())
state = Registry.BLOCK.get(render.renderNameBlock().get()).defaultBlockState();
{
state = BuiltInRegistries.BLOCK.get(render.renderNameBlock().get()).get().value().defaultBlockState();
}
}
Optional<ModelOverride> ov = ModelOverrideHandler.getModelOverride(state, carry.getContentNbt());
@ -265,16 +308,20 @@ public class CarryRenderHelper
return state;
}
/*
@Deprecated
public static BakedModel getRenderBlock(Player player)
{
CarryOnData carry = CarryOnDataManager.getCarryData(player);
ItemRenderer renderer = Minecraft.getInstance().getItemRenderer();
Minecraft.getInstance().getModelManager().specialBlockModelRenderer().get().
BlockState state = getRenderState(player);
BakedModel model = Minecraft.getInstance().getBlockRenderer().getBlockModel(state);
if(state.getRenderShape() != RenderShape.MODEL || model.isCustomRenderer() || model.getQuads(state, null, RandomSource.create()).size() <= 0) {
ItemStack stack = new ItemStack(state.getBlock());
model = renderer.getModel(stack, player.level, player, 0);
model = renderer.getModel(stack, player.level(), player, 0);
}
Optional<ModelOverride> ov = ModelOverrideHandler.getModelOverride(state, carry.getContentNbt());
@ -282,26 +329,29 @@ public class CarryRenderHelper
{
var renderObj = ov.get().getRenderObject();
if(renderObj.left().isPresent())
model = renderer.getModel(renderObj.left().get(), player.level, player, 0);
model = renderer.getModel(renderObj.left().get(), player.level(), player, 0);
}
return model;
}
*/
public static Entity getRenderEntity(Player player)
{
CarryOnData carry = CarryOnDataManager.getCarryData(player);
Entity entity = carry.getEntity(player.level);
Entity entity = carry.getEntity(player.level());
if(carry.getActiveScript().isPresent())
{
CarryOnScript script = carry.getActiveScript().get();
ScriptRender render = script.scriptRender();
if(render.renderNameEntity().isPresent())
entity = Registry.ENTITY_TYPE.get(render.renderNameEntity().get()).create(player.level);
entity = BuiltInRegistries.ENTITY_TYPE.get(render.renderNameEntity().get()).get().value().create(player.level(), EntitySpawnReason.EVENT);
if(render.renderNBT().isPresent())
entity.load(render.renderNBT().get());
if(render.renderNBT().isPresent()) {
ValueInput input = TagValueInput.create(new ProblemReporter.ScopedCollector(Constants.LOG), player.registryAccess(), render.renderNBT().get());
entity.load(input);
}
}
return entity;
@ -313,7 +363,7 @@ public class CarryRenderHelper
if(carry.isCarrying(CarryType.BLOCK))
{
BlockState state = getRenderState(player);
VoxelShape shape = state.getShape(player.level, player.blockPosition());
VoxelShape shape = state.getShape(player.level(), player.blockPosition());
if(shape == null || shape.isEmpty())
return 1f;
Optional<ModelOverride> ov = ModelOverrideHandler.getModelOverride(state, carry.getContentNbt());
@ -329,7 +379,10 @@ public class CarryRenderHelper
else if(carry.isCarrying(CarryType.ENTITY))
{
Entity entity = getRenderEntity(player);
return entity.getBbWidth();
float w = entity.getBbWidth();
if (Constants.CLIENT_CONFIG.rotateEntitiesSideways)
return w - (w*w) * 0.35f;
return w * 0.9f;
}
else
return 1f;
@ -341,7 +394,7 @@ public class CarryRenderHelper
if(carry.isCarrying(CarryType.BLOCK))
{
BlockState state = getRenderState(player);
VoxelShape shape = state.getShape(player.level, player.blockPosition());
VoxelShape shape = state.getShape(player.level(), player.blockPosition());
if(shape == null || shape.isEmpty())
return 1f;
Optional<ModelOverride> ov = ModelOverrideHandler.getModelOverride(state, carry.getContentNbt());
@ -387,7 +440,7 @@ public class CarryRenderHelper
public static boolean isChest(Block block)
{
return block == Blocks.CHEST || block == Blocks.ENDER_CHEST || block == Blocks.TRAPPED_CHEST;
return block == Blocks.CHEST || block == Blocks.ENDER_CHEST || block == Blocks.TRAPPED_CHEST || block instanceof ChestBlock;
}
}

View File

@ -0,0 +1,22 @@
package tschipp.carryon.client.render;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.player.PlayerModel;
import net.minecraft.client.renderer.SubmitNodeCollector;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.client.renderer.entity.state.AvatarRenderState;
public class CarryingItemRenderLayer<M extends PlayerModel> extends RenderLayer<AvatarRenderState, M> {
public CarryingItemRenderLayer(RenderLayerParent<AvatarRenderState, M> renderer) {
super(renderer);
}
@Override
public void submit(PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight,
AvatarRenderState renderState, float yRot, float xRot) {
if (renderState instanceof ICarryOnRenderState carryOnRenderState){
CarriedObjectRender.draw(carryOnRenderState.getPlayer(), poseStack, packedLight, Minecraft.getInstance().getDeltaTracker().getGameTimeDeltaPartialTick(true), nodeCollector,false);
}
}
}

View File

@ -0,0 +1,20 @@
package tschipp.carryon.client.render;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.common.carry.CarryOnData;
public interface ICarryOnRenderState {
CarryOnData getCarryOnData();
void setCarryOnData(CarryOnData data);
float getRenderWidth();
void setRenderWidth(float val);
Player getPlayer();
void setPlayer(Player player);
}

View File

@ -1,21 +1,57 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.carry;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.AreaEffectCloud;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.level.storage.TagValueOutput;
import net.minecraft.world.level.storage.ValueInput;
import tschipp.carryon.Constants;
import tschipp.carryon.common.scripting.CarryOnScript;
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.UUID;
public class CarryOnData {
@ -24,30 +60,56 @@ public class CarryOnData {
private boolean keyPressed = false;
private CarryOnScript activeScript;
private int selectedSlot = 0;
private static final ProblemReporter problemReporter = new ProblemReporter.ScopedCollector(Constants.LOG);
public static final Codec<CarryOnData> CODEC = CompoundTag.CODEC.flatXmap(
tag -> {
try {
return DataResult.success(new CarryOnData(tag));
} catch (Exception e) {
return DataResult.error(e::getMessage);
}
},
carry -> {
try {
return DataResult.success(carry.getNbt());
} catch (Exception e) {
return DataResult.error(e::getMessage);
}
}
);
public static final StreamCodec<RegistryFriendlyByteBuf, CarryOnData> STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC);
public static final String SERIALIZATION_KEY = "CarryOnData";
public CarryOnData(CompoundTag data)
{
if(data.contains("type"))
this.type = CarryType.valueOf(data.getString("type"));
this.type = CarryType.valueOf(data.getStringOr("type", "INVALID"));
else
this.type = CarryType.INVALID;
this.nbt = data;
if(data.contains("keyPressed"))
this.keyPressed = data.getBoolean("keyPressed");
this.keyPressed = data.getBooleanOr("keyPressed", false);
if(data.contains("activeScript"))
{
DataResult<CarryOnScript> res = CarryOnScript.CODEC.parse(NbtOps.INSTANCE, data.get("activeScript"));
this.activeScript = res.getOrThrow(false, (s) -> {throw new RuntimeException("Failed to decode activeScript during CarryOnData serialization: " + s);});
this.activeScript = res.getOrThrow((s) -> {throw new RuntimeException("Failed to decode activeScript during CarryOnData serialization: " + s);});
}
if(data.contains("selected"))
this.selectedSlot = data.getInt("selected");
this.selectedSlot = data.getIntOr("selected", 0);
}
public CarryType getType()
{
return this.type;
}
public CompoundTag getNbt()
{
nbt.putString("type", type.toString());
@ -55,7 +117,7 @@ public class CarryOnData {
if(activeScript != null)
{
DataResult<Tag> res = CarryOnScript.CODEC.encodeStart(NbtOps.INSTANCE, activeScript);
Tag tag = res.getOrThrow(false, (s) -> {throw new RuntimeException("Failed to encode activeScript during CarryOnData serialization: " + s);});
Tag tag = res.getOrThrow((s) -> {throw new RuntimeException("Failed to encode activeScript during CarryOnData serialization: " + s);});
nbt.put("activeScript", tag);
}
nbt.putInt("selected", this.selectedSlot);
@ -65,13 +127,13 @@ public class CarryOnData {
public CompoundTag getContentNbt()
{
if(type == CarryType.BLOCK && nbt.contains("block"))
return nbt.getCompound("block");
return nbt.getCompoundOrEmpty("block");
else if(type == CarryType.ENTITY && nbt.contains("entity"))
return nbt.getCompound("entity");
return nbt.getCompoundOrEmpty("entity");
return null;
}
public void setBlock(BlockState state, @Nullable BlockEntity tile)
public void setBlock(BlockState state, @Nullable BlockEntity tile, ServerPlayer player, BlockPos pos)
{
this.type = CarryType.BLOCK;
@ -83,7 +145,9 @@ public class CarryOnData {
if(tile != null)
{
CompoundTag tileData = tile.saveWithId();
TagValueOutput output = TagValueOutput.createWithContext(problemReporter, player.registryAccess());
tile.saveWithId(output);
Tag tileData = output.buildResult();
nbt.put("tile", tileData);
}
}
@ -93,11 +157,11 @@ public class CarryOnData {
if(this.type != CarryType.BLOCK)
throw new IllegalStateException("Called getBlock on data that contained " + this.type);
return NbtUtils.readBlockState(nbt.getCompound("block"));
return NbtUtils.readBlockState(BuiltInRegistries.BLOCK, nbt.getCompoundOrEmpty("block"));
}
@Nullable
public BlockEntity getBlockEntity(BlockPos pos)
public BlockEntity getBlockEntity(BlockPos pos, HolderLookup.Provider lookup)
{
if(this.type != CarryType.BLOCK)
throw new IllegalStateException("Called getBlockEntity on data that contained " + this.type);
@ -105,14 +169,15 @@ public class CarryOnData {
if(!nbt.contains("tile"))
return null;
return BlockEntity.loadStatic(pos, this.getBlock(), nbt.getCompound("tile"));
return BlockEntity.loadStatic(pos, this.getBlock(), nbt.getCompoundOrEmpty("tile"), lookup);
}
public void setEntity(Entity entity)
{
this.type = CarryType.ENTITY;
CompoundTag entityData = new CompoundTag();
entity.save(entityData);
TagValueOutput output = TagValueOutput.createWithContext(new ProblemReporter.ScopedCollector(Constants.LOG), entity.registryAccess());
entity.save(output);
Tag entityData = output.buildResult();
nbt.put("entity", entityData);
}
@ -121,7 +186,14 @@ public class CarryOnData {
if(this.type != CarryType.ENTITY)
throw new IllegalStateException("Called getEntity on data that contained " + this.type);
return EntityType.create(nbt.getCompound("entity"), level).orElseThrow(() -> new IllegalStateException("Called EntityType#create even though no entity data was present. Data: " + nbt.toString()));
ValueInput in = TagValueInput.create(problemReporter, level.registryAccess(), nbt.getCompoundOrEmpty("entity"));
var optionalEntity = EntityType.create(in, level, EntitySpawnReason.BUCKET);
if(optionalEntity.isPresent())
return optionalEntity.get();
Constants.LOG.error("Called EntityType#create even though no entity data was present. Data: " + nbt.toString());
this.clear();
return new AreaEffectCloud(level, 0, 0, 0);
}
public Optional<CarryOnScript> getActiveScript()
@ -136,8 +208,20 @@ public class CarryOnData {
this.activeScript = script;
}
public void setCarryingPlayer() {
public void setCarryingPlayer(Player player)
{
this.type = CarryType.PLAYER;
nbt.putString("player", player.getStringUUID().toString());
}
public Player getCarryingPlayer(Level level)
{
if(this.type != CarryType.PLAYER)
throw new IllegalStateException("Called getCarryingPlayer on data that contained " + this.type);
if(!nbt.contains("player"))
return null;
UUID uuid = UUID.fromString(nbt.getString("player").get());
return level.getServer().getPlayerList().getPlayer(uuid);
}
public boolean isCarrying()
@ -172,13 +256,20 @@ public class CarryOnData {
this.activeScript = null;
}
public CarryOnData clone() {
return new CarryOnData(nbt.copy());
}
public int getTick()
{
if(!this.nbt.contains("tick"))
return -1;
return this.nbt.getInt("tick");
return this.nbt.getIntOr("tick", -1);
}
public void setTick(int tick) {
this.nbt.putInt("tick", tick);
}
public enum CarryType {
BLOCK,
ENTITY,

View File

@ -1,28 +1,40 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.carry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.platform.Services;
public class CarryOnDataManager {
public static final EntityDataAccessor<CompoundTag> CARRY_DATA_KEY = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG);
public static CarryOnData getCarryData(Player player)
{
CompoundTag data = player.getEntityData().get(CARRY_DATA_KEY);
return new CarryOnData(data.copy());
return Services.PLATFORM.getCarryData(player);
}
public static void setCarryData(Player player, CarryOnData data)
{
data.setSelected(player.getInventory().selected);
CompoundTag nbt = data.getNbt();
nbt.putInt("tick", player.tickCount);
player.getEntityData().set(CARRY_DATA_KEY, nbt);
data.setSelected(player.getInventory().getSelectedSlot());
data.setTick(player.tickCount);
Services.PLATFORM.setCarryData(player, data);
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.carry;
import net.minecraft.core.BlockPos;
@ -5,26 +25,30 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.AgeableMob;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.*;
import net.minecraft.world.entity.Entity.RemovalReason;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.storage.TagValueOutput;
import net.minecraft.world.phys.Vec3;
import tschipp.carryon.CarryOnCommon;
import tschipp.carryon.Constants;
import tschipp.carryon.common.config.ListHandler;
import tschipp.carryon.common.pickupcondition.PickupCondition;
import tschipp.carryon.common.pickupcondition.PickupConditionHandler;
import tschipp.carryon.common.scripting.CarryOnScript;
import tschipp.carryon.common.scripting.ScriptManager;
import tschipp.carryon.networking.clientbound.ClientboundStartRidingPacket;
import tschipp.carryon.networking.clientbound.ClientboundStartRidingOtherPlayerPacket;
import tschipp.carryon.platform.Services;
import javax.annotation.Nullable;
@ -72,16 +96,26 @@ public class PickupHandler {
BlockEntity blockEntity = level.getBlockEntity(pos);
BlockState state = level.getBlockState(pos);
CompoundTag nbt = null;
if(blockEntity != null)
nbt = blockEntity.saveWithId();
if(blockEntity != null) {
TagValueOutput output = TagValueOutput.createWithContext(new ProblemReporter.ScopedCollector(Constants.LOG), level.registryAccess());
blockEntity.saveWithId(output);
nbt = output.buildResult();
}
Optional<CarryOnScript> result = ScriptManager.inspectBlock(state, level, pos, nbt);
boolean overrideChecks = result.map(CarryOnScript::overrideChecks).orElse(false);
if(!ListHandler.isPermitted(state.getBlock()))
return false;
if(state.getDestroySpeed(level, pos) == -1 && !player.isCreative())
// Reject pickup of Double blocks, if they use the vanilla property
if(hasPropertyType(state, DoorBlock.HALF))
return false;
if(blockEntity == null && !Constants.COMMON_CONFIG.settings.pickupAllBlocks)
if(!overrideChecks && (state.getDestroySpeed(level, pos) == -1 && !player.isCreative() && !Constants.COMMON_CONFIG.settings.pickupUnbreakableBlocks))
return false;
if(!overrideChecks && (blockEntity == null && !Constants.COMMON_CONFIG.settings.pickupAllBlocks))
return false;
//Check if TE is locked
@ -102,7 +136,6 @@ public class PickupHandler {
if(!doPickup)
return false;
Optional<CarryOnScript> result = ScriptManager.inspectBlock(state, level, pos, nbt);
if(result.isPresent())
{
CarryOnScript script = result.get();
@ -113,10 +146,10 @@ public class PickupHandler {
String cmd = script.scriptEffects().commandInit();
if(!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
player.level().getServer().getCommands().performPrefixedCommand(player.level().getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().name() + " run " + cmd);
}
carry.setBlock(state, blockEntity);
carry.setBlock(state, blockEntity, player, pos);
level.removeBlockEntity(pos);
level.removeBlock(pos, false);
@ -124,6 +157,8 @@ public class PickupHandler {
CarryOnDataManager.setCarryData(player, carry);
level.playSound(null, pos, state.getSoundType().getHitSound(), SoundSource.BLOCKS, 1.0f, 0.5f);
player.swing(InteractionHand.MAIN_HAND, true);
if (!player.isCreative() || Constants.COMMON_CONFIG.settings.slownessInCreative)
player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 100000000, CarryOnCommon.potionLevel(carry, player.level()), false, false));
return true;
}
@ -137,25 +172,34 @@ public class PickupHandler {
if (entity.invulnerableTime != 0)
return false;
if(entity.isRemoved())
return false;
if (entity instanceof TamableAnimal tame)
{
UUID owner = tame.getOwnerUUID();
UUID playerID = player.getGameProfile().getId();
if (owner != null && !owner.equals(playerID))
return false;
EntityReference<LivingEntity> ref = tame.getOwnerReference();
if (ref != null) {
UUID owner = ref.getUUID();
UUID playerID = player.getGameProfile().id();
if (!owner.equals(playerID))
return false;
}
}
Optional<CarryOnScript> result = ScriptManager.inspectEntity(entity);
boolean overrideChecks = result.map(CarryOnScript::overrideChecks).orElse(false);
if(!ListHandler.isPermitted(entity))
{
//We can pick up baby animals even if the grown up animal is blacklisted.
if(!(entity instanceof AgeableMob ageableMob && Constants.COMMON_CONFIG.settings.allowBabies && (ageableMob.getAge() < 0 || ageableMob.isBaby())))
if(!overrideChecks && (!(entity instanceof AgeableMob ageableMob && Constants.COMMON_CONFIG.settings.allowBabies && (ageableMob.getAge() < 0 || ageableMob.isBaby()))))
return false;
}
//Non-Creative only guards
if(!player.isCreative())
{
if(!Constants.COMMON_CONFIG.settings.pickupHostileMobs && entity.getType().getCategory() == MobCategory.MONSTER)
if(!overrideChecks && (!Constants.COMMON_CONFIG.settings.pickupHostileMobs && entity.getType().getCategory() == MobCategory.MONSTER))
return false;
if(Constants.COMMON_CONFIG.settings.maxEntityHeight < entity.getBbHeight() || Constants.COMMON_CONFIG.settings.maxEntityWidth < entity.getBbWidth())
@ -169,13 +213,12 @@ public class PickupHandler {
return false;
}
boolean doPickup = pickupCallback == null ? true : pickupCallback.apply(entity);
boolean doPickup = pickupCallback == null || pickupCallback.apply(entity);
if(!doPickup)
return false;
CarryOnData carry = CarryOnDataManager.getCarryData(player);
Optional<CarryOnScript> result = ScriptManager.inspectEntity(entity);
if(result.isPresent())
{
CarryOnScript script = result.get();
@ -198,15 +241,17 @@ public class PickupHandler {
if (result.isPresent()) {
String cmd = result.get().scriptEffects().commandInit();
if (!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
player.level().getServer().getCommands().performPrefixedCommand(player.level().getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().name() + " run " + cmd);
}
otherPlayer.startRiding(player);
Services.PLATFORM.sendPacketToPlayer(Constants.PACKET_ID_START_RIDING, new ClientboundStartRidingPacket(otherPlayer.getId(), true), player);
carry.setCarryingPlayer();
otherPlayer.startRiding(player, true, false);
Services.PLATFORM.sendPacketToAllPlayers(Constants.PACKET_ID_START_RIDING_OTHER, new ClientboundStartRidingOtherPlayerPacket(player.getId(), otherPlayer.getId(), true), player.level());
carry.setCarryingPlayer(otherPlayer);
player.swing(InteractionHand.MAIN_HAND, true);
player.level.playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC, SoundSource.AMBIENT, 1.0f, 0.5f);
player.level().playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC.value(), SoundSource.AMBIENT, 1.0f, 0.5f);
CarryOnDataManager.setCarryData(player, carry);
if (!player.isCreative() || Constants.COMMON_CONFIG.settings.slownessInCreative)
player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 100000000, CarryOnCommon.potionLevel(carry, player.level()), false, false));
return true;
}
@ -214,23 +259,33 @@ public class PickupHandler {
entity.ejectPassengers();
entity.stopRiding();
if (entity instanceof Animal animal) {
animal.dropLeash(true, true);
animal.dropLeash();
}
if(result.isPresent())
{
String cmd = result.get().scriptEffects().commandInit();
if(!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
player.level().getServer().getCommands().performPrefixedCommand(player.level().getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().name() + " run " + cmd);
}
carry.setEntity(entity);
entity.remove(RemovalReason.UNLOADED_WITH_PLAYER);
player.level.playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC, SoundSource.AMBIENT, 1.0f, 0.5f);
player.level().playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC.value(), SoundSource.AMBIENT, 1.0f, 0.5f);
CarryOnDataManager.setCarryData(player, carry);
player.swing(InteractionHand.MAIN_HAND, true);
if (!player.isCreative() || Constants.COMMON_CONFIG.settings.slownessInCreative)
player.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 100000000, CarryOnCommon.potionLevel(carry, player.level()), false, false));
return true;
}
private static <T extends Comparable<T>> boolean hasPropertyType(BlockState state, Property<T> prop) {
for (var p : state.getProperties()) {
if(p.getValueClass().equals(prop.getValueClass()))
return true;
}
return false;
}
}

View File

@ -1,25 +1,44 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.carry;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.animal.horse.Horse;
import net.minecraft.world.entity.animal.equine.Horse;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.gamerules.GameRules;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
@ -27,8 +46,12 @@ import tschipp.carryon.Constants;
import tschipp.carryon.common.carry.CarryOnData.CarryType;
import tschipp.carryon.common.config.ListHandler;
import tschipp.carryon.common.scripting.CarryOnScript.ScriptEffects;
import tschipp.carryon.networking.clientbound.ClientboundStartRidingOtherPlayerPacket;
import tschipp.carryon.platform.Services;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.BiFunction;
@ -44,7 +67,7 @@ public class PlacementHandler
if (player.tickCount == carry.getTick())
return false;
Level level = player.getLevel();
Level level = player.level();
BlockState state = carry.getBlock();
BlockPlaceContext context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(player.position(), facing, pos));
@ -54,7 +77,7 @@ public class PlacementHandler
context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(player.position(), facing, pos));
BlockEntity blockEntity = carry.getBlockEntity(pos);
BlockEntity blockEntity = carry.getBlockEntity(pos, level.registryAccess());
state = getPlacementState(state, player, context, pos);
@ -69,22 +92,29 @@ public class PlacementHandler
if (!doPlace)
return false;
if(level.isOutsideBuildHeight(pos))
return false;
if (carry.getActiveScript().isPresent()) {
ScriptEffects effects = carry.getActiveScript().get().scriptEffects();
String cmd = effects.commandPlace();
if (!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
player.level().getServer().getCommands().performPrefixedCommand(player.level().getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().name() + " run " + cmd);
}
level.setBlockAndUpdate(pos, state);
if (blockEntity != null)
if (blockEntity != null) {
blockEntity.setBlockState(state);
level.setBlockEntity(blockEntity);
}
level.updateNeighborsAt(pos.relative(Direction.DOWN), level.getBlockState(pos.relative(Direction.DOWN)).getBlock());
carry.clear();
CarryOnDataManager.setCarryData(player, carry);
player.playSound(state.getSoundType().getPlaceSound(), 1.0f, 0.5f);
level.playSound(null, pos, state.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0f, 0.5f);
player.swing(InteractionHand.MAIN_HAND, true);
player.removeEffect(MobEffects.SLOWNESS);
return true;
}
@ -95,7 +125,7 @@ public class PlacementHandler
placementState = state;
for (var prop : placementState.getProperties()) {
if (prop instanceof DirectionProperty)
if (prop.getValueClass() == Direction.class)
state = updateProperty(state, placementState, prop);
if (prop.getValueClass() == Direction.Axis.class)
state = updateProperty(state, placementState, prop);
@ -105,7 +135,7 @@ public class PlacementHandler
}
}
BlockState updatedState = Block.updateFromNeighbourShapes(state, player.level, pos);
BlockState updatedState = Block.updateFromNeighbourShapes(state, player.level(), pos);
if (updatedState.getBlock() == state.getBlock())
state = updatedState;
@ -131,23 +161,30 @@ public class PlacementHandler
if (player.tickCount == carry.getTick())
return false;
Level level = player.getLevel();
Level level = player.level();
BlockPlaceContext context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(player.position(), facing, pos));
if (!level.getBlockState(pos).canBeReplaced(context))
if (!level.getBlockState(pos).canBeReplaced(context)) {
pos = pos.relative(facing);
context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(player.position(), facing, pos));
}
if (!level.getBlockState(pos).canBeReplaced(context)) {
level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.LAVA_POP, SoundSource.PLAYERS, 0.5F, 0.5F);
return false;
}
Vec3 placementPos = Vec3.atBottomCenterOf(pos);
if (carry.isCarrying(CarryType.PLAYER)) {
Entity otherPlayer = player.getFirstPassenger();
Entity otherPlayer = carry.getCarryingPlayer(level);
player.ejectPassengers();
Services.PLATFORM.sendPacketToAllPlayers(Constants.PACKET_ID_START_RIDING_OTHER, new ClientboundStartRidingOtherPlayerPacket(player.getId(), otherPlayer.getId(), false), player.level());
carry.clear();
CarryOnDataManager.setCarryData(player, carry);
if (otherPlayer == null)
return true;
otherPlayer.teleportTo(placementPos.x, placementPos.y, placementPos.z);
otherPlayer.teleportTo(placementPos.x, placementPos.y, placementPos.z);
player.swing(InteractionHand.MAIN_HAND, true);
player.removeEffect(MobEffects.SLOWNESS);
return true;
}
@ -162,7 +199,7 @@ public class PlacementHandler
ScriptEffects effects = carry.getActiveScript().get().scriptEffects();
String cmd = effects.commandPlace();
if (!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
player.level().getServer().getCommands().performPrefixedCommand(player.level().getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().name() + " run " + cmd);
}
level.addFreshEntity(entity);
@ -172,6 +209,7 @@ public class PlacementHandler
player.swing(InteractionHand.MAIN_HAND, true);
carry.clear();
CarryOnDataManager.setCarryData(player, carry);
player.removeEffect(MobEffects.SLOWNESS);
return true;
}
@ -184,13 +222,15 @@ public class PlacementHandler
if (!carry.isCarrying(CarryType.ENTITY) && !carry.isCarrying(CarryType.PLAYER))
return;
Level level = player.level;
Level level = player.level();
Entity entityHeld;
if (carry.isCarrying(CarryType.ENTITY))
entityHeld = carry.getEntity(level);
else
entityHeld = player.getFirstPassenger();
if(entityHeld == null)
return;
double sizeHeldEntity = entityHeld.getBbHeight() * entityHeld.getBbWidth();
double distance = entityClicked.blockPosition().distSqr(player.blockPosition());
@ -204,7 +244,7 @@ public class PlacementHandler
if (ListHandler.isStackingPermitted(topEntity)) {
double sizeEntity = topEntity.getBbHeight() * topEntity.getBbWidth();
if (Constants.COMMON_CONFIG.settings.entitySizeMattersStacking && sizeHeldEntity <= sizeEntity || !Constants.COMMON_CONFIG.settings.entitySizeMattersStacking) {
if (!Constants.COMMON_CONFIG.settings.entitySizeMattersStacking || sizeHeldEntity <= sizeEntity) {
if (topEntity instanceof Horse horse)
horse.setTamed(true);
@ -217,26 +257,27 @@ public class PlacementHandler
level.addFreshEntity(entityHeld);
entityHeld.teleportTo(tempX, tempY, tempZ);
}
entityHeld.startRiding(topEntity, false);
entityHeld.startRiding(topEntity, false,false);
} else {
if (carry.isCarrying(CarryType.ENTITY)) {
entityHeld.setPos(entityClicked.getX(), entityClicked.getY(), entityClicked.getZ());
level.addFreshEntity(entityHeld);
}
entityHeld.startRiding(topEntity, false);
entityHeld.startRiding(topEntity, false,false);
}
if (carry.getActiveScript().isPresent()) {
ScriptEffects effects = carry.getActiveScript().get().scriptEffects();
String cmd = effects.commandPlace();
if (!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
player.level().getServer().getCommands().performPrefixedCommand(player.level().getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().name() + " run " + cmd);
}
player.swing(InteractionHand.MAIN_HAND, true);
carry.clear();
CarryOnDataManager.setCarryData(player, carry);
level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.HORSE_SADDLE, SoundSource.PLAYERS, 0.5F, 1.5F);
player.removeEffect(MobEffects.SLOWNESS);
} else {
level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.LAVA_POP, SoundSource.PLAYERS, 0.5F, 0.5F);
}
@ -249,10 +290,10 @@ public class PlacementHandler
public static void placeCarriedOnDeath(ServerPlayer oldPlayer, ServerPlayer newPlayer, boolean died)
{
CarryOnData carry = CarryOnDataManager.getCarryData(oldPlayer);
if (oldPlayer.level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || !died) {
if (oldPlayer.level().getGameRules().get(GameRules.KEEP_INVENTORY) || !died) {
if (!carry.isCarrying(CarryType.PLAYER)) {
CarryOnDataManager.setCarryData(newPlayer, carry);
newPlayer.getInventory().selected = oldPlayer.getInventory().selected;
newPlayer.getInventory().setSelectedSlot(oldPlayer.getInventory().getSelectedSlot());
return;
}
}
@ -264,50 +305,55 @@ public class PlacementHandler
{
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if (carry.isCarrying(CarryType.ENTITY)) {
Entity entity = carry.getEntity(player.level);
Entity entity = carry.getEntity(player.level());
entity.setPos(player.position());
player.level.addFreshEntity(entity);
player.level().addFreshEntity(entity);
} else if (carry.isCarrying(CarryType.BLOCK)) {
BlockPlaceContext context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(Vec3.atCenterOf(player.blockPosition()), Direction.DOWN, player.blockPosition()));
BlockState state = getPlacementState(carry.getBlock(), player, context, player.blockPosition());
BlockPos pos = getDeathPlacementPos(state, player);
BlockEntity blockEntity = carry.getBlockEntity(pos);
player.level.setBlock(pos, state, 3);
BlockEntity blockEntity = carry.getBlockEntity(pos, player.level().registryAccess());
player.level().setBlock(pos, state, 3);
if (blockEntity != null)
player.level.setBlockEntity(blockEntity);
player.level().setBlockEntity(blockEntity);
} else if (carry.isCarrying(CarryType.PLAYER)) {
player.ejectPassengers();
}
carry.clear();
CarryOnDataManager.setCarryData(player, carry);
player.removeEffect(MobEffects.SLOWNESS);
}
private static BlockPos getDeathPlacementPos(BlockState state, ServerPlayer player)
{
MutableBlockPos pos = new MutableBlockPos();
BlockPos p = player.blockPosition();
int DISTANCE = 15;
List<BlockPos> potentialPositions = new ArrayList<>();
for (int j = 0; j < DISTANCE * 2; j++) {
for (int i = 0; i < DISTANCE * 2; i++) {
for (int k = 0; k < DISTANCE * 2; k++) {
int x = i % 2 == 0 ? i / 2 : -(i / 2);
int y = j % 2 == 0 ? j / 2 : -(j / 2);
int z = k % 2 == 0 ? k / 2 : -(k / 2);
pos.set(p.getX() + x, p.getY() + y, p.getZ() + z);
BlockPlaceContext context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(Vec3.atCenterOf(pos), Direction.DOWN, pos));
boolean canPlace = state.canSurvive(player.level, pos) && player.level.getBlockState(pos).canBeReplaced(context) && player.level.isUnobstructed(state, pos, CollisionContext.of(player));
if (canPlace)
return pos;
potentialPositions.add(new BlockPos(p.getX() + x, p.getY() + y, p.getZ() + z));
}
}
}
potentialPositions.sort(Comparator.comparingDouble(posA -> player.distanceToSqr(posA.getCenter())));
for(BlockPos potential : potentialPositions)
{
BlockPlaceContext context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(Vec3.atCenterOf(potential), Direction.DOWN, potential));
boolean canPlace = state.canSurvive(player.level(), potential) && player.level().getBlockState(potential).canBeReplaced(context) && player.level().isUnobstructed(state, potential, CollisionContext.of(player));
if (canPlace)
return potential;
}
return p;
}

View File

@ -0,0 +1,25 @@
package tschipp.carryon.common.carry.compat;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nullable;
public class CarryOnModHooks {
public record CanPickupBlockHook(ServerPlayer player, BlockPos pos, BlockState state) {
}
public record CanPickupEntityHook(ServerPlayer player, Entity entity) {
}
public record SaveBlockHook(ServerPlayer player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity) {
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.command;
import com.mojang.brigadier.CommandDispatcher;
@ -8,6 +28,8 @@ import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.permissions.Permission;
import net.minecraft.server.permissions.PermissionLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.state.BlockState;
import tschipp.carryon.Constants;
@ -34,11 +56,11 @@ public class CommandCarryOn
.then(Commands.literal("clear").executes(cmd -> handleClear(cmd.getSource(), Collections.singleton(cmd.getSource().getPlayerOrException()))))
.then(Commands.literal("clear").then(Commands.argument("target", EntityArgument.players()).requires(src -> src.hasPermission(2)).executes(cmd -> handleClear(cmd.getSource(), EntityArgument.getPlayers(cmd, "target")))))
.then(Commands.literal("clear").then(Commands.argument("target", EntityArgument.players()).requires(src -> src.permissions().hasPermission(new Permission.HasCommandLevel(PermissionLevel.GAMEMASTERS))).executes(cmd -> handleClear(cmd.getSource(), EntityArgument.getPlayers(cmd, "target")))))
.then(Commands.literal("place").requires(src -> src.hasPermission(2)).executes(cmd -> handlePlace(cmd.getSource(), Collections.singleton(cmd.getSource().getPlayerOrException()))))
.then(Commands.literal("place").requires(src -> src.permissions().hasPermission(new Permission.HasCommandLevel(PermissionLevel.GAMEMASTERS))).executes(cmd -> handlePlace(cmd.getSource(), Collections.singleton(cmd.getSource().getPlayerOrException()))))
.then(Commands.literal("place").then(Commands.argument("target", EntityArgument.players()).requires(src -> src.hasPermission(2)).executes(cmd -> handlePlace(cmd.getSource(), EntityArgument.getPlayers(cmd, "target")))))
.then(Commands.literal("place").then(Commands.argument("target", EntityArgument.players()).requires(src -> src.permissions().hasPermission(new Permission.HasCommandLevel(PermissionLevel.GAMEMASTERS))).executes(cmd -> handlePlace(cmd.getSource(), EntityArgument.getPlayers(cmd, "target")))))
;
@ -75,7 +97,7 @@ public class CommandCarryOn
}
else if (carry.isCarrying(CarryType.ENTITY))
{
Entity entity = carry.getEntity(player.level);
Entity entity = carry.getEntity(player.level());
log(source,"Entity: " + entity);
log(source,"Entity Name: " + entity.getType());
log(source,"NBT: " + carry.getNbt());
@ -112,11 +134,14 @@ public class CommandCarryOn
cleared++;
}
int finalCleared = cleared;
if (cleared != 1)
source.sendSuccess(Component.literal("Cleared " + cleared + " Items!"), true);
else
source.sendSuccess(Component.literal("Cleared " + cleared + " Item!"), true);
if (cleared != 1) {
source.sendSuccess(() -> Component.literal("Cleared " + finalCleared + " Items!"), true);
}
else {
source.sendSuccess(() -> Component.literal("Cleared " + finalCleared + " Item!"), true);
}
return 1;
}
@ -129,18 +154,20 @@ public class CommandCarryOn
PlacementHandler.placeCarried(player);
cleared++;
}
int finalCleared = cleared;
if (cleared != 1)
source.sendSuccess(Component.literal("Placed " + cleared + " Items!"), true);
if (cleared != 1) {
source.sendSuccess(() -> Component.literal("Placed " + finalCleared + " Items!"), true);
}
else
source.sendSuccess(Component.literal("Placed " + cleared + " Item!"), true);
source.sendSuccess(() -> Component.literal("Placed " + finalCleared + " Item!"), true);
return 1;
}
private static void log(CommandSourceStack source, String toLog)
{
source.sendSuccess(Component.literal(toLog), true);
source.sendSuccess(() -> Component.literal(toLog), true);
Constants.LOG.info(toLog);
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.config;
import tschipp.carryon.config.PropertyType;
@ -5,302 +25,355 @@ import tschipp.carryon.config.annotations.Category;
import tschipp.carryon.config.annotations.Config;
import tschipp.carryon.config.annotations.Property;
public class CarryConfig {
public class CarryConfig
{
@Config("carryon-common")
public static class Common {
//Settings
@Property(
type = PropertyType.CATEGORY,
description = "General Settings"
)
public Settings settings = new Settings();
@Config("carryon-common")
public static class Common
{
//Settings
@Property(
type = PropertyType.CATEGORY,
description = "General Settings"
)
public Settings settings = new Settings();
@Category("settings")
public static class Settings {
@Property(
type = PropertyType.DOUBLE,
description = "Maximum distance from where Blocks and Entities can be picked up",
minD = 0
)
public double maxDistance = 2.5;
@Category(value="settings", translation = "carryon.category.settings")
public static class Settings
{
@Property(
type = PropertyType.DOUBLE,
description = "Maximum distance from where Blocks and Entities can be picked up",
minD = 0
)
public double maxDistance = 2.5;
@Property(
type = PropertyType.DOUBLE,
description = "Max width of entities that can be picked up in survival mode",
minD = 0,
maxD = 10
)
public double maxEntityWidth = 1.5;
@Property(
type = PropertyType.DOUBLE,
description = "Max width of entities that can be picked up in survival mode",
minD = 0,
maxD = 10
)
public double maxEntityWidth = 1.5;
@Property(
type = PropertyType.DOUBLE,
description = "Max height of entities that can be picked up in survival mode",
minD = 0,
maxD = 10
)
public double maxEntityHeight = 2.5;
@Property(
type = PropertyType.DOUBLE,
description = "Max height of entities that can be picked up in survival mode",
minD = 0,
maxD = 10
)
public double maxEntityHeight = 2.5;
@Property(
type = PropertyType.DOUBLE,
description = "Slowness multiplier for blocks",
minD = 0
)
public double blockSlownessMultiplier = 1;
@Property(
type = PropertyType.DOUBLE,
description = "Slowness multiplier for blocks",
minD = 0
)
public double blockSlownessMultiplier = 1;
@Property(
type = PropertyType.DOUBLE,
description = "Slowness multiplier for entities",
minD = 0
)
public double entitySlownessMultiplier = 1;
@Property(
type = PropertyType.DOUBLE,
description = "Slowness multiplier for entities",
minD = 0
)
public double entitySlownessMultiplier = 1;
@Property(
type = PropertyType.INT,
description = "Maximum stack limit for entities",
min = 1
)
public int maxEntityStackLimit = 10;
@Property(
type = PropertyType.INT,
description = "Maximum stack limit for entities",
min = 1
)
public int maxEntityStackLimit = 10;
@Property(
type = PropertyType.BOOLEAN,
description = "More complex Tile Entities slow down the player more"
)
public boolean heavyTiles = true;
@Property(
type = PropertyType.BOOLEAN,
description = "More complex Tile Entities slow down the player more"
)
public boolean heavyTiles = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Allow all blocks to be picked up, not just Tile Entites. White/Blacklist will still be respected."
)
public boolean pickupAllBlocks = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Allow all blocks to be picked up, not just Tile Entites. White/Blacklist will still be respected."
)
public boolean pickupAllBlocks = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether Blocks and Entities slow the creative player down when carried"
)
public boolean slownessInCreative = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether Blocks and Entities slow the creative player down when carried"
)
public boolean slownessInCreative = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether hostile mobs should be able to picked up in survival mode"
)
public boolean pickupHostileMobs = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether hostile mobs should be able to picked up in survival mode"
)
public boolean pickupHostileMobs = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Larger Entities slow down the player more"
)
public boolean heavyEntities = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Larger Entities slow down the player more"
)
public boolean heavyEntities = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Allow babies to be carried even when adult mob is blacklisted (or not whitelisted)"
)
public boolean allowBabies = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Allow babies to be carried even when adult mob is blacklisted (or not whitelisted)"
)
public boolean allowBabies = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Use Whitelist instead of Blacklist for Blocks"
)
public boolean useWhitelistBlocks = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Use Whitelist instead of Blacklist for Blocks"
)
public boolean useWhitelistBlocks = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Use Whitelist instead of Blacklist for Entities"
)
public boolean useWhitelistEntities = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Use Whitelist instead of Blacklist for Entities"
)
public boolean useWhitelistEntities = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Use Whitelist instead of Blacklist for Stacking"
)
public boolean useWhitelistStacking = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Use Whitelist instead of Blacklist for Stacking"
)
public boolean useWhitelistStacking = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether the player can hit blocks and entities while carrying or not"
)
public boolean hitWhileCarrying = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether the player can hit blocks and entities while carrying or not"
)
public boolean hitWhileCarrying = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether the player drops the carried object when hit or not"
)
public boolean dropCarriedWhenHit = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether the player drops the carried object when hit or not"
)
public boolean dropCarriedWhenHit = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Use custom Pickup Scripts. Having this set to false, will not allow you to run scripts, but will increase your performance"
)
public boolean useScripts = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Use custom Pickup Scripts. Having this set to false, will not allow you to run scripts, but will increase your performance"
)
public boolean useScripts = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Allows entities to be stacked on top of each other"
)
public boolean stackableEntities = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Allows entities to be stacked on top of each other"
)
public boolean stackableEntities = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether entities' size matters when stacking or not. This means that larger entities cannot be stacked on smaller ones"
)
public boolean entitySizeMattersStacking = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether entities' size matters when stacking or not. This means that larger entities cannot be stacked on smaller ones"
)
public boolean entitySizeMattersStacking = true;
@Property(
type = PropertyType.STRING_ARRAY,
description = "Usually all the block state information is retained when placing a block that was picked up. But some information is changed to a modified property, like rotation or orientation. In this list, add additional properties that should NOT be saved and instead be updated when placed. Format: modid:block[propertyname]. Note: You don't need to add an entry for every subtype of a same block. For example, we only add an entry for one type of slab, but the change is applied to all slabs."
)
public String[] placementStateExceptions = {
"minecraft:chest[type]",
"minecraft:stone_button[face]",
"minecraft:vine[north,east,south,west,up]",
"minecraft:creeper_head[rotation]",
"minecraft:glow_lichen[north,east,south,west,up,down]",
"minecraft:oak_sign[rotation]",
"minecraft:oak_trapdoor[half]",
};
@Property(
type = PropertyType.STRING_ARRAY,
description = "Usually all the block state information is retained when placing a block that was picked up. But some information is changed to a modified property, like rotation or orientation. In this list, add additional properties that should NOT be saved and instead be updated when placed. Format: modid:block[propertyname]. Note: You don't need to add an entry for every subtype of a same block. For example, we only add an entry for one type of slab, but the change is applied to all slabs.",
validationRegex = "([a-zA-Z0-9_]+:[a-zA-Z0-9_]+)\\[([a-zA-Z0-9_,]+)\\]"
)
public String[] placementStateExceptions = {
"minecraft:chest[type]",
"minecraft:stone_button[face]",
"minecraft:vine[north,east,south,west,up]",
"minecraft:creeper_head[rotation]",
"minecraft:glow_lichen[north,east,south,west,up,down]",
"minecraft:oak_sign[rotation]",
"minecraft:oak_trapdoor[half]",
};
@Property(
type = PropertyType.BOOLEAN,
description = "Whether Players can be picked up. Creative players can't be picked up in Survival Mode"
)
public boolean pickupPlayers = true;
@Property(
type = PropertyType.BOOLEAN,
description = "Whether players in Survival Mode can pick up unbreakable blocks. Creative players always can."
)
public boolean pickupUnbreakableBlocks = false;
}
@Property(
type = PropertyType.CATEGORY,
description = "Whitelist. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Black---and-Whitelist-Config"
)
@Property(
type = PropertyType.CATEGORY,
description = "Whitelist. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Black---and-Whitelist-Config"
)
//Whitelist
public Whitelist whitelist = new Whitelist();
@Category("whitelist")
public static class Whitelist {
@Property(
type = PropertyType.STRING_ARRAY,
description = "Entities that CAN be picked up (useWhitelistEntities must be true)"
)
public String[] allowedEntities = {};
//Whitelist
public Whitelist whitelist = new Whitelist();
@Property(
type = PropertyType.STRING_ARRAY,
description = "Blocks that CAN be picked up (useWhitelistBlocks must be true)"
)
public String[] allowedBlocks = {};
@Category(value="whitelist", translation = "carryon.category.whitelist")
public static class Whitelist
{
@Property(
type = PropertyType.STRING_ARRAY,
description = "Entities that CAN be picked up (useWhitelistEntities must be true)",
validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)"
)
public String[] allowedEntities = {};
@Property(
type = PropertyType.STRING_ARRAY,
description = "Entities that CAN have other entities stacked on top of them (useWhitelistStacking must be true)"
)
public String[] allowedStacking = {};
}
@Property(
type = PropertyType.STRING_ARRAY,
description = "Blocks that CAN be picked up (useWhitelistBlocks must be true)",
validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)"
)
public String[] allowedBlocks = {};
//Blacklist
@Property(
type = PropertyType.CATEGORY,
description = "Blacklist. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Black---and-Whitelist-Config"
)
public Blacklist blacklist = new Blacklist();
@Category("blacklist")
public static class Blacklist {
@Property(
type = PropertyType.STRING_ARRAY,
description = "Blocks that cannot be picked up"
)
public String[] forbiddenTiles = {
"#forge:immovable", "#forge:relocation_not_supported", "minecraft:end_portal", "minecraft:piston_head",
"minecraft:end_gateway", "minecraft:tall_grass", "minecraft:large_fern", "minecraft:peony",
"minecraft:rose_bush", "minecraft:lilac", "minecraft:sunflower", "minecraft:*_bed",
"minecraft:*_door", "minecraft:big_dripleaf_stem", "minecraft:waterlily", "minecraft:cake",
"minecraft:nether_portal", "minecraft:tall_seagrass", "animania:block_trough",
"animania:block_invisiblock", "colossalchests:*", "ic2:*", "bigreactors:*", "forestry:*",
"tconstruct:*", "rustic:*", "botania:*", "astralsorcery:*", "quark:colored_bed_*",
"immersiveengineering:*", "embers:block_furnace", "embers:ember_bore",
"embers:ember_activator", "embers:mixer", "embers:heat_coil", "embers:large_tank",
"embers:crystal_cell", "embers:alchemy_pedestal", "embers:boiler", "embers:combustor",
"embers:catalzyer", "embers:field_chart", "embers:inferno_forge",
"storagedrawers:framingtable", "skyresources:*", "lootbags:*", "exsartagine:*",
"aquamunda:tank", "opencomputers:*", "malisisdoors:*", "industrialforegoing:*",
"minecolonies:*", "thaumcraft:pillar*", "thaumcraft:infernal_furnace",
"thaumcraft:placeholder*", "thaumcraft:infusion_matrix", "thaumcraft:golem_builder",
"thaumcraft:thaumatorium*", "magneticraft:oil_heater", "magneticraft:solar_panel",
"magneticraft:steam_engine", "magneticraft:shelving_unit", "magneticraft:grinder",
"magneticraft:sieve", "magneticraft:solar_tower", "magneticraft:solar_mirror",
"magneticraft:container", "magneticraft:pumpjack", "magneticraft:solar_panel",
"magneticraft:refinery", "magneticraft:oil_heater", "magneticraft:hydraulic_press",
"magneticraft:multiblock_gap", "refinedstorage:*", "mcmultipart:*", "enderstorage:*",
"betterstorage:*", "practicallogistics2:*", "wearablebackpacks:*", "rftools:screen",
"rftools:creative_screen", "create:*", "magic_doorknob:*", "iceandfire:*", "ftbquests:*",
"waystones:*", "contact:*", "framedblocks:*"
};
@Property(
type = PropertyType.STRING_ARRAY,
description = "Entities that CAN have other entities stacked on top of them (useWhitelistStacking must be true)",
validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)"
)
public String[] allowedStacking = {};
}
@Property(
type = PropertyType.STRING_ARRAY,
description = "Entities that cannot be picked up"
)
public String[] forbiddenEntities = {
"minecraft:end_crystal", "minecraft:ender_dragon", "minecraft:ghast",
"minecraft:shulker", "minecraft:leash_knot", "minecraft:armor_stand",
"minecraft:item_frame", "minecraft:painting", "minecraft:shulker_bullet",
"animania:hamster", "animania:ferret*", "animania:hedgehog*", "animania:cart",
"animania:wagon", "mynko:*", "pixelmon:*", "mocreatures:*", "quark:totem", "vehicle:*"
};
//Blacklist
@Property(
type = PropertyType.CATEGORY,
description = "Blacklist. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Black---and-Whitelist-Config"
)
public Blacklist blacklist = new Blacklist();
@Property(
type = PropertyType.STRING_ARRAY,
description = "Entities that cannot have other entities stacked on top of them"
)
public String[] forbiddenStacking = {
"minecraft:horse"
};
}
@Category(value="blacklist", translation = "carryon.category.blacklist")
public static class Blacklist
{
@Property(
type = PropertyType.STRING_ARRAY,
description = "Blocks that cannot be picked up",
validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)"
)
public String[] forbiddenTiles = {
"#forge:immovable", "#forge:relocation_not_supported", "#neoforge:immovable", "#neoforge:relocation_not_supported", "minecraft:end_portal", "minecraft:piston_head",
"#c:relocation_not_supported",
"minecraft:end_gateway", "minecraft:tall_grass", "minecraft:large_fern", "minecraft:peony",
"minecraft:rose_bush", "minecraft:lilac", "minecraft:sunflower", "minecraft:*_bed",
"minecraft:*_door", "minecraft:big_dripleaf_stem", "minecraft:waterlily", "minecraft:cake",
"minecraft:nether_portal", "minecraft:tall_seagrass", "animania:block_trough",
"animania:block_invisiblock", "colossalchests:*", "ic2:*", "bigreactors:*", "forestry:*",
"tconstruct:*", "rustic:*", "botania:*", "astralsorcery:*", "quark:colored_bed_*",
"immersiveengineering:*", "embers:block_furnace", "embers:ember_bore",
"embers:ember_activator", "embers:mixer", "embers:heat_coil", "embers:large_tank",
"embers:crystal_cell", "embers:alchemy_pedestal", "embers:boiler", "embers:combustor",
"embers:catalzyer", "embers:field_chart", "embers:inferno_forge",
"storagedrawers:framingtable", "skyresources:*", "lootbags:*", "exsartagine:*",
"aquamunda:tank", "opencomputers:*", "malisisdoors:*", "industrialforegoing:*",
"minecolonies:*", "thaumcraft:pillar*", "thaumcraft:infernal_furnace",
"thaumcraft:placeholder*", "thaumcraft:infusion_matrix", "thaumcraft:golem_builder",
"thaumcraft:thaumatorium*", "magneticraft:oil_heater", "magneticraft:solar_panel",
"magneticraft:steam_engine", "magneticraft:shelving_unit", "magneticraft:grinder",
"magneticraft:sieve", "magneticraft:solar_tower", "magneticraft:solar_mirror",
"magneticraft:container", "magneticraft:pumpjack", "magneticraft:solar_panel",
"magneticraft:refinery", "magneticraft:oil_heater", "magneticraft:hydraulic_press",
"magneticraft:multiblock_gap", "refinedstorage:*", "mcmultipart:*", "enderstorage:*",
"betterstorage:*", "practicallogistics2:*", "wearablebackpacks:*", "rftools:screen",
"rftools:creative_screen", "create:*", "magic_doorknob:*", "iceandfire:*", "ftbquests:*",
"waystones:*", "contact:*", "framedblocks:*", "securitycraft:*", "forgemultipartcbe:*", "integrateddynamics:cable",
"mekanismgenerators:wind_generator", "cookingforblockheads:cabinet", "cookingforblockheads:corner", "cookingforblockheads:counter",
"cookingforblockheads:oven", "cookingforblockheads:toaster", "cookingforblockheads:milk_jar", "cookingforblockheads:cow_jar",
"cookingforblockheads:fruit_basket", "cookingforblockheads:cooking_table", "cookingforblockheads:fridge", "cookingforblockheads:sink",
"chipped:*", "irons_spellbooks:*", "create*:*", "simple_pipes:*", "libmultipart:*", "quark:tiny_potato", "ait:*",
"vampirism:*", "extrastorage:*", "relics:researching_table", "sophisticatedstorage:*chest",
"powah:*", "advancementtrophies:trophy", "mekanismgenerators:heat_generator", "mna:filler_block", "create_enchantment_industry:*", "graveyard:*", "immersivepetroleum:*",
"tardis:interior_door", "cuffed:*", "littletiles:*",
"butchersdelight:*", "irons_spellbooks:*", "extended_drawers:*", "functionalstorage:*", "sophisticatedstorage:*", "farmersdelight:*",
"modern_industrialization:*_cable",
"modern_industrialization:item_pipe",
"modern_industrialization:*_item_pipe",
"modern_industrialization:fluid_pipe",
"modern_industrialization:*_fluid_pipe",
"yigd:*", "domum_ornamentum:*", "connectiblechains:*",
"cobblemon:*", "snowrealmagic:*", "forbidden_arcanus:black_hole", "domum_ornamentum:*", "sgjourney:*", "copycats:*", "expandedstorage:*", "replication:*"
};
//Custom Pickup Conditions
@Property(
type = PropertyType.CATEGORY,
description = "Custom Pickup Conditions. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Custom-Pickup-Condition-Config"
)
public CustomPickupConditions customPickupConditions = new CustomPickupConditions();
@Category("customPickupConditions")
public static class CustomPickupConditions {
@Property(
type = PropertyType.STRING_ARRAY,
description = "Custom Pickup Conditions for Blocks"
)
public String[] customPickupConditionsBlocks = {};
@Property(
type = PropertyType.STRING_ARRAY,
description = "Entities that cannot be picked up",
validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)"
)
public String[] forbiddenEntities = {
"#c:capturing_not_supported", "#c:teleporting_not_supported",
"minecraft:end_crystal", "minecraft:ender_dragon", "minecraft:ghast", "minecraft:fireball", "minecraft:small_fireball", "minecraft:whither_skull",
"minecraft:shulker", "minecraft:leash_knot", "minecraft:armor_stand", "minecraft:whither_skull_dangerous", "minecraft:dragon_fireball",
"minecraft:item_frame", "minecraft:painting", "minecraft:shulker_bullet", "minecraft:evoker_fangs", "minecraft:glow_item_frame", "minecraft:tnt", "minecraft:trident", "minecraft:arrow", "minecraft:spectral_arrow",
"minecraft:interaction", "minecraft:marker", "minecraft:block_display", "minecraft:item_display", "minecraft:text_display",
"animania:hamster", "animania:ferret*", "animania:hedgehog*", "animania:cart",
"animania:wagon", "mynko:*", "pixelmon:*", "mocreatures:*", "quark:totem", "vehicle:*",
"securitycraft:*", "taterzens:npc", "easy_npc:*", "bodiesbodies:dead_body", "littletiles:*",
"connectiblechains:*", "cobblemon:*", "create:*", "swem:*", "toms_mobs:*"
};
@Property(
type = PropertyType.STRING_ARRAY,
description = "Custom Pickup Conditions for Entities"
)
public String[] customPickupConditionsEntities = {};
}
}
@Property(
type = PropertyType.STRING_ARRAY,
description = "Entities that cannot have other entities stacked on top of them",
validationRegex = "(#?[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]*(?:\\*|[a-zA-Z0-9_]*)(?:\\*|[a-zA-Z0-9_]*)?)"
)
public String[] forbiddenStacking = {
"minecraft:horse",
"minecraft:ender_dragon"
};
}
@Config("carryon-client")
public static class Client {
//Custom Pickup Conditions
@Property(
type = PropertyType.CATEGORY,
description = "Custom Pickup Conditions. Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Custom-Pickup-Condition-Config"
)
public CustomPickupConditions customPickupConditions = new CustomPickupConditions();
@Property(
type = PropertyType.BOOLEAN,
description = "If the front of the Tile Entities should face the player or should face outward"
)
public boolean facePlayer = false;
@Category(value="customPickupConditions", translation = "carryon.category.custompickupconditions")
public static class CustomPickupConditions
{
@Property(
type = PropertyType.STRING_ARRAY,
description = "Custom Pickup Conditions for Blocks",
validationRegex = "([a-zA-Z0-9_*\\-:]+(?:\\[[^\\]]*\\])?)\\(([\\w_]+)\\)"
)
public String[] customPickupConditionsBlocks = {};
@Property(
type = PropertyType.BOOLEAN,
description = "Arms should render on sides when carrying. Set to false if you experience issues with mods that replace the player model (like MoBends, etc)"
)
public boolean renderArms = true;
@Property(
type = PropertyType.STRING_ARRAY,
description = "Custom Pickup Conditions for Entities",
validationRegex = "([a-zA-Z0-9_*\\-:]+(?:\\[[^\\]]*\\])?)\\(([\\w_]+)\\)"
)
public String[] customPickupConditionsEntities = {};
}
}
@Property(
type = PropertyType.STRING_ARRAY,
description = "Model Overrides based on NBT or Meta. Advanced users only! Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Model-Override-Config"
)
public String[] modelOverrides = {
"minecraft:redstone_wire->(item)minecraft:redstone",
"minecraft:bamboo_sapling->(block)minecraft:bamboo",
"minecraft:candle_cake->(block)minecraft:cake"
};
}
@Config("carryon-client")
public static class Client
{
@Property(
type = PropertyType.BOOLEAN,
description = "If the front of the Tile Entities should face the player or should face outward"
)
public boolean facePlayer = false;
@Property(
type = PropertyType.BOOLEAN,
description = "If Entities should be rotated sideways when carried"
)
public boolean rotateEntitiesSideways = false;
@Property(
type = PropertyType.BOOLEAN,
description = "Arms should render on sides when carrying. Set to false if you experience issues with mods that replace the player model (like MoBends, etc)"
)
public boolean renderArms = true;
@Property(
type = PropertyType.STRING_ARRAY,
description = "Model Overrides based on NBT or Meta. Advanced users only! Read about the format here: https://github.com/Tschipp/CarryOn/wiki/Model-Override-Config",
validationRegex = "([a-zA-Z0-9_]+:[a-zA-Z0-9_]+(?:\\[[^\\]]*\\])?(?:\\{[^}]*\\})?)(?:;(\\d+))?->(?:\\((item|block)\\))?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+(?:\\[[^\\]]*\\])?(?:\\{[^}]*\\})?)(?:;(\\d+))?"
)
public String[] modelOverrides = {
"minecraft:redstone_wire->(item)minecraft:redstone",
"minecraft:bamboo_sapling->(block)minecraft:bamboo",
"minecraft:candle_cake->(block)minecraft:cake"
};
}
}

View File

@ -1,8 +1,28 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.config;
import com.mojang.datafixers.kinds.Const;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
@ -30,9 +50,7 @@ public class ListHandler {
private static List<TagKey<EntityType<?>>> FORBIDDEN_STACKING_TAGS = new ArrayList<>();
private static List<TagKey<EntityType<?>>> ALLOWED_STACKING_TAGS = new ArrayList<>();
private static Set<Class<?>> PROPERTY_EXCEPTION_CLASSES = new HashSet<>();
private static Set<Property<?>> PROPERTY_EXCEPTION_CLASSES = new HashSet<>();
public static boolean isPermitted(Block block)
{
@ -60,12 +78,12 @@ public class ListHandler {
public static boolean isPropertyException(Property<?> prop)
{
return PROPERTY_EXCEPTION_CLASSES.contains(prop.getValueClass());
return PROPERTY_EXCEPTION_CLASSES.contains(prop);
}
private static boolean doCheck(Block block, Set<String> regular, List<TagKey<Block>> tags)
{
String name = Registry.BLOCK.getKey(block).toString();
String name = BuiltInRegistries.BLOCK.getKey(block).toString();
if(regular.contains(name))
return true;
for(TagKey<Block> tag : tags)
@ -76,7 +94,7 @@ public class ListHandler {
private static boolean doCheck(Entity entity, Set<String> regular, List<TagKey<EntityType<?>>> tags)
{
String name = Registry.ENTITY_TYPE.getKey(entity.getType()).toString();
String name = BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString();
if(regular.contains(name))
return true;
for(TagKey<EntityType<?>> tag : tags)
@ -101,32 +119,32 @@ public class ListHandler {
ALLOWED_TILES_TAGS.clear();
PROPERTY_EXCEPTION_CLASSES.clear();
Map<ResourceLocation, TagKey<Block>> blocktags = Registry.BLOCK.getTagNames().collect(Collectors.toMap(t -> t.location(), t -> t));
Map<ResourceLocation, TagKey<EntityType<?>>> entitytags = Registry.ENTITY_TYPE.getTagNames().collect(Collectors.toMap(t -> t.location(), t -> t));
Map<Identifier, TagKey<Block>> blocktags = BuiltInRegistries.BLOCK.listTagIds().collect(Collectors.toMap(t -> t.location(), t -> t));
Map<Identifier, TagKey<EntityType<?>>> entitytags = BuiltInRegistries.ENTITY_TYPE.listTagIds().collect(Collectors.toMap(t -> t.location(), t -> t));
List<String> forbidden = new ArrayList<>(List.of(Constants.COMMON_CONFIG.blacklist.forbiddenTiles));
forbidden.add("#carryon:block_blacklist");
addWithWildcards(forbidden, FORBIDDEN_TILES, Registry.BLOCK, blocktags, FORBIDDEN_TILES_TAGS);
addWithWildcards(forbidden, FORBIDDEN_TILES, BuiltInRegistries.BLOCK, blocktags, FORBIDDEN_TILES_TAGS);
List<String> forbiddenEntity = new ArrayList<>(List.of(Constants.COMMON_CONFIG.blacklist.forbiddenEntities));
forbiddenEntity.add("#carryon:entity_blacklist");
addWithWildcards(forbiddenEntity, FORBIDDEN_ENTITIES, Registry.ENTITY_TYPE, entitytags, FORBIDDEN_ENTITIES_TAGS);
addWithWildcards(forbiddenEntity, FORBIDDEN_ENTITIES, BuiltInRegistries.ENTITY_TYPE, entitytags, FORBIDDEN_ENTITIES_TAGS);
List<String> allowedEntities = new ArrayList<>(List.of(Constants.COMMON_CONFIG.whitelist.allowedEntities));
allowedEntities.add("#carryon:entity_whitelist");
addWithWildcards(allowedEntities, ALLOWED_ENTITIES, Registry.ENTITY_TYPE, entitytags, ALLOWED_ENTITIES_TAGS);
addWithWildcards(allowedEntities, ALLOWED_ENTITIES, BuiltInRegistries.ENTITY_TYPE, entitytags, ALLOWED_ENTITIES_TAGS);
List<String> allowedBlocks = new ArrayList<>(List.of(Constants.COMMON_CONFIG.whitelist.allowedBlocks));
allowedBlocks.add("#carryon:block_whitelist");
addWithWildcards(allowedBlocks, ALLOWED_TILES, Registry.BLOCK, blocktags, ALLOWED_TILES_TAGS);
addWithWildcards(allowedBlocks, ALLOWED_TILES, BuiltInRegistries.BLOCK, blocktags, ALLOWED_TILES_TAGS);
List<String> forbiddenStacking = new ArrayList<>(List.of(Constants.COMMON_CONFIG.blacklist.forbiddenStacking));
forbiddenStacking.add("#carryon:stacking_blacklist");
addWithWildcards(forbiddenStacking, FORBIDDEN_STACKING, Registry.ENTITY_TYPE, entitytags, FORBIDDEN_STACKING_TAGS);
addWithWildcards(forbiddenStacking, FORBIDDEN_STACKING, BuiltInRegistries.ENTITY_TYPE, entitytags, FORBIDDEN_STACKING_TAGS);
List<String> allowedStacking = new ArrayList<>(List.of(Constants.COMMON_CONFIG.whitelist.allowedStacking));
allowedStacking.add("#carryon:stacking_whitelist");
addWithWildcards(allowedStacking, ALLOWED_STACKING, Registry.ENTITY_TYPE, entitytags, ALLOWED_STACKING_TAGS);
addWithWildcards(allowedStacking, ALLOWED_STACKING, BuiltInRegistries.ENTITY_TYPE, entitytags, ALLOWED_STACKING_TAGS);
for(String propString : Constants.COMMON_CONFIG.settings.placementStateExceptions)
{
@ -134,26 +152,26 @@ public class ListHandler {
continue;
String name = propString.substring(0, propString.indexOf("["));
String props = propString.substring(propString.indexOf("[") + 1, propString.indexOf("]"));
Block blk = Registry.BLOCK.get(new ResourceLocation(name));
Block blk = BuiltInRegistries.BLOCK.get(Identifier.parse(name)).get().value();
for(String propName : props.split(",")) {
for (Property<?> prop : blk.defaultBlockState().getProperties()) {
if (prop.getName().equals(propName))
PROPERTY_EXCEPTION_CLASSES.add(prop.getValueClass());
PROPERTY_EXCEPTION_CLASSES.add(prop);
}
}
}
}
private static <T> void addTag(String tag, Map<ResourceLocation, TagKey<T>> tagMap, List<TagKey<T>> tags) {
private static <T> void addTag(String tag, Map<Identifier, TagKey<T>> tagMap, List<TagKey<T>> tags) {
String sub = tag.substring(1);
TagKey<T> t = tagMap.get(new ResourceLocation(sub));
TagKey<T> t = tagMap.get(Identifier.parse(sub));
if (t != null)
tags.add(t);
}
private static <T> void addWithWildcards(List<String> entries, Set<String> toAddTo, Registry<T> registry, Map<ResourceLocation, TagKey<T>> tags, List<TagKey<T>> toAddTags) {
private static <T> void addWithWildcards(List<String> entries, Set<String> toAddTo, Registry<T> registry, Map<Identifier, TagKey<T>> tags, List<TagKey<T>> toAddTags) {
ResourceLocation[] keys = registry.keySet().toArray(new ResourceLocation[0]);
Identifier[] keys = registry.keySet().toArray(new Identifier[0]);
for (int i = 0; i < entries.size(); i++)
{
String curr = entries.get(i);
@ -163,7 +181,7 @@ public class ListHandler {
{
String[] filter = curr.replace("*", ",").split(",");
for (ResourceLocation key : keys)
for (Identifier key : keys)
{
if (containsAll(key.toString(), filter))

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.pickupcondition;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -5,7 +25,7 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import net.minecraft.commands.arguments.blocks.BlockStateParser;
import net.minecraft.commands.arguments.blocks.BlockStateParser.BlockResult;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.state.BlockState;
@ -32,7 +52,7 @@ public class PickupCondition
public static DataResult<PickupCondition> of(String str)
{
if(!(str.contains("(") && str.endsWith(")")))
return DataResult.error("Error while parsing: "+ str +". Pickup Condition must contain proper brackets.");
return DataResult.error(() -> "Error while parsing: "+ str +". Pickup Condition must contain proper brackets.");
String cond = str.substring(str.indexOf("(") + 1, str.length()-1);
@ -51,7 +71,7 @@ public class PickupCondition
{
String name = match.contains("[") ? match.substring(0, match.indexOf("[")) : match;
String[] split = name.replace("*", ",").split(",");
String stateName = Registry.BLOCK.getKey(state.getBlock()).toString();
String stateName = BuiltInRegistries.BLOCK.getKey(state.getBlock()).toString();
if(StringHelper.matchesWildcards(stateName, split))
{
@ -76,7 +96,7 @@ public class PickupCondition
public boolean matches(Entity entity)
{
String entityName = Registry.ENTITY_TYPE.getKey(entity.getType()).toString();
String entityName = BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString();
if(wildcards)
{
String[] split = match.replace("*", ",").split(",");
@ -99,7 +119,7 @@ public class PickupCondition
private BlockResult parseState(String state)
{
try {
BlockResult result = BlockStateParser.parseForBlock(Registry.BLOCK, state, false);
BlockResult result = BlockStateParser.parseForBlock(BuiltInRegistries.BLOCK, state, false);
return result;
} catch (CommandSyntaxException e) {
e.printStackTrace();

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.pickupcondition;
import com.mojang.serialization.DataResult;

View File

@ -1,8 +1,28 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.scripting;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerPlayer;
@ -19,12 +39,13 @@ public record CarryOnScript(
ScriptObject scriptObject,
ScriptConditions scriptConditions,
ScriptRender scriptRender,
ScriptEffects scriptEffects)
ScriptEffects scriptEffects,
boolean overrideChecks)
{
public boolean isValid()
{
return (isBlock() ^ isEntity()) && (scriptConditions != ScriptConditions.EMPTY || scriptRender != ScriptRender.EMPTY || scriptEffects != ScriptEffects.EMPTY);
return (isBlock() ^ isEntity()) && (scriptConditions != ScriptConditions.EMPTY || scriptRender != ScriptRender.EMPTY || scriptEffects != ScriptEffects.EMPTY || overrideChecks);
}
public boolean isBlock()
@ -43,7 +64,8 @@ public record CarryOnScript(
ScriptObject.CODEC.fieldOf("object").forGetter(CarryOnScript::scriptObject),
ScriptConditions.CODEC.optionalFieldOf("conditions", ScriptConditions.EMPTY).forGetter(CarryOnScript::scriptConditions),
ScriptRender.CODEC.optionalFieldOf("render", ScriptRender.EMPTY).forGetter(CarryOnScript::scriptRender),
ScriptEffects.CODEC.optionalFieldOf("effects", ScriptEffects.EMPTY).forGetter(CarryOnScript::scriptEffects)
ScriptEffects.CODEC.optionalFieldOf("effects", ScriptEffects.EMPTY).forGetter(CarryOnScript::scriptEffects),
Codec.BOOL.optionalFieldOf("override_checks", false).forGetter(CarryOnScript::overrideChecks)
).apply(instance, CarryOnScript::new)
);
@ -74,17 +96,15 @@ public record CarryOnScript(
public record ScriptObjectBlock(
Optional<ResourceKey<Block>> typeNameBlock,
MaterialCondition typeMaterial,
NumberBoundCondition typeHardness,
NumberBoundCondition typeResistance,
NBTCondition typeBlockTag
){
public static final ScriptObjectBlock EMPTY = new ScriptObjectBlock(Optional.empty(), MaterialCondition.NONE, NumberBoundCondition.NONE, NumberBoundCondition.NONE, NBTCondition.NONE);
public static final ScriptObjectBlock EMPTY = new ScriptObjectBlock(Optional.empty(), NumberBoundCondition.NONE, NumberBoundCondition.NONE, NBTCondition.NONE);
public static final Codec<ScriptObjectBlock> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ResourceKey.codec(Registry.BLOCK_REGISTRY).optionalFieldOf("name").forGetter(ScriptObjectBlock::typeNameBlock),
MaterialCondition.CODEC.optionalFieldOf("material", MaterialCondition.NONE).forGetter(ScriptObjectBlock::typeMaterial),
ResourceKey.codec(Registries.BLOCK).optionalFieldOf("name").forGetter(ScriptObjectBlock::typeNameBlock),
NumberBoundCondition.CODEC.optionalFieldOf("hardness", NumberBoundCondition.NONE).forGetter(ScriptObjectBlock::typeHardness),
NumberBoundCondition.CODEC.optionalFieldOf("resistance", NumberBoundCondition.NONE).forGetter(ScriptObjectBlock::typeResistance),
NBTCondition.CODEC.optionalFieldOf("nbt", NBTCondition.NONE).forGetter(ScriptObjectBlock::typeBlockTag)
@ -103,7 +123,7 @@ public record CarryOnScript(
public static final Codec<ScriptObjectEntity> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ResourceKey.codec(Registry.ENTITY_TYPE_REGISTRY).optionalFieldOf("name").forGetter(ScriptObjectEntity::typeNameEntity),
ResourceKey.codec(Registries.ENTITY_TYPE).optionalFieldOf("name").forGetter(ScriptObjectEntity::typeNameEntity),
NumberBoundCondition.CODEC.optionalFieldOf("health", NumberBoundCondition.NONE).forGetter(ScriptObjectEntity::typeHealth),
NumberBoundCondition.CODEC.optionalFieldOf("height", NumberBoundCondition.NONE).forGetter(ScriptObjectEntity::typeHeight),
NumberBoundCondition.CODEC.optionalFieldOf("width", NumberBoundCondition.NONE).forGetter(ScriptObjectEntity::typeWidth),
@ -153,8 +173,8 @@ public record CarryOnScript(
public static final Codec<ScriptRender> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
ResourceKey.codec(Registry.BLOCK_REGISTRY).optionalFieldOf("name_block").forGetter(ScriptRender::renderNameBlock),
ResourceKey.codec(Registry.ENTITY_TYPE_REGISTRY).optionalFieldOf("name_entity").forGetter(ScriptRender::renderNameEntity),
ResourceKey.codec(Registries.BLOCK).optionalFieldOf("name_block").forGetter(ScriptRender::renderNameBlock),
ResourceKey.codec(Registries.ENTITY_TYPE).optionalFieldOf("name_entity").forGetter(ScriptRender::renderNameEntity),
CompoundTag.CODEC.optionalFieldOf("nbt").forGetter(ScriptRender::renderNBT),
OptionalVec3.CODEC.optionalFieldOf("translation", OptionalVec3.NONE).forGetter(ScriptRender::renderTranslation),
OptionalVec3.CODEC.optionalFieldOf("rotation", OptionalVec3.NONE).forGetter(ScriptRender::renderRotation),

View File

@ -1,23 +1,44 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.scripting;
import com.mojang.serialization.Codec;
import net.minecraft.advancements.Advancement;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraft.server.ServerAdvancementManager;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.Score;
import net.minecraft.world.scores.Scoreboard;
import tschipp.carryon.platform.Services;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
public final class Matchables
{
@ -29,9 +50,7 @@ public final class Matchables
private static float getValueFromStringOrDefault(String toGetFrom, String key, float defaultVal)
{
Optional<Float> val = getValueFromString(toGetFrom, key);
if(val.isPresent())
return val.get();
return defaultVal;
return val.orElse(defaultVal);
}
private static Optional<Float> getValueFromString(String toGetFrom, String key)
@ -99,91 +118,6 @@ public final class Matchables
}
}
public record MaterialCondition(String material) implements Matchable<Material>
{
public static final Codec<MaterialCondition> CODEC = Codec.STRING.xmap(MaterialCondition::new, MaterialCondition::material);
public static final MaterialCondition NONE = new MaterialCondition("");
@Override
public boolean matches(Material material)
{
if (this.material == null || this.material.isEmpty())
return true;
switch (this.material) {
case "air":
return material == Material.AIR;
case "anvil":
return material == Material.HEAVY_METAL;
case "barrier":
return material == Material.BARRIER;
case "cactus":
return material == Material.CACTUS;
case "cake":
return material == Material.CAKE;
case "carpet":
return material == Material.CLOTH_DECORATION;
case "clay":
return material == Material.CLAY;
case "cloth":
return material == Material.WOOL;
case "dragon_egg":
return material == Material.EGG;
case "fire":
return material == Material.FIRE;
case "glass":
return material == Material.GLASS;
case "gourd":
return material == Material.VEGETABLE;
case "grass":
return material == Material.GRASS;
case "ground":
return material == Material.GRASS;
case "ice":
return material == Material.ICE;
case "iron":
return material == Material.METAL;
case "lava":
return material == Material.LAVA;
case "leaves":
return material == Material.LEAVES;
case "packed_ice":
return material == Material.ICE_SOLID;
case "piston":
return material == Material.PISTON;
case "plants":
return material == Material.PLANT;
case "portal":
return material == Material.PORTAL;
case "redstone_light":
return material == Material.BUILDABLE_GLASS;
case "rock":
return material == Material.STONE;
case "sand":
return material == Material.SAND;
case "snow":
return material == Material.TOP_SNOW;
case "sponge":
return material == Material.SPONGE;
case "structure_void":
return material == Material.STRUCTURAL_AIR;
case "tnt":
return material == Material.EXPLOSIVE;
case "vine":
return material == Material.PLANT;
case "water":
return material == Material.WATER;
case "web":
return material == Material.WEB;
case "wood":
return material == Material.WOOD;
default:
return false;
}
}
}
public record AdvancementCondition(String advancement) implements Matchable<ServerPlayer>
{
public static final Codec<AdvancementCondition> CODEC = Codec.STRING.xmap(AdvancementCondition::new, AdvancementCondition::advancement);
@ -193,8 +127,8 @@ public final class Matchables
@Override
public boolean matches(ServerPlayer player)
{
ServerAdvancementManager manager = player.server.getAdvancements();
Advancement adv = manager.getAdvancement(new ResourceLocation(advancement.isEmpty() ? "" : advancement));
ServerAdvancementManager manager = player.level().getServer().getAdvancements();
AdvancementHolder adv = manager.get(Identifier.parse(advancement.isEmpty() ? "" : advancement));
boolean achievement = adv == null ? true : player.getAdvancements().getOrStartProgress(adv).isDone();
return achievement;
@ -233,34 +167,25 @@ public final class Matchables
if (cond == null || cond.isEmpty())
return true;
Scoreboard score = player.getScoreboard();
Scoreboard score = player.level().getScoreboard();
String numb;
String scorename;
int iE = cond.indexOf("=");
int iG = cond.indexOf(">");
int iL = cond.indexOf("<");
if (iG == -1 ? true : iE < iG && iL == -1 ? true : iE < iL && iE != -1)
if (iG == -1 || (iE < iG && iL == -1 || iE < iL && iE != -1))
numb = cond.substring(iE);
else if (iE == -1 ? true : iG < iE && iL == -1 ? true : iG < iL && iG != -1)
else if (iE == -1 || (iG < iE && iL == -1 || iG < iL && iG != -1))
numb = cond.substring(iG);
else
numb = cond.substring(iL);
scorename = cond.replace(numb, "");
Map<Objective, Score> o = score.getPlayerScores(player.getGameProfile().getName());
if (o != null)
{
Score sc = o.get(score.getObjective(scorename));
if (sc != null)
{
int points = sc.getScore();
Object2IntMap<Objective> scores = score.listPlayerScores(player);
int scoreVal = scores.getInt(score.getObjective(scorename));
return new NumberBoundCondition(numb).matches(points);
}
}
return false;
return new NumberBoundCondition(numb).matches(scoreVal);
}
}
@ -277,8 +202,8 @@ public final class Matchables
if (cond == null || cond.isEmpty())
return true;
BlockPos blockpos = new BlockPos(getValueFromStringOrDefault(cond, "x", 0), getValueFromStringOrDefault(cond, "y", 0), getValueFromStringOrDefault(cond, "z", 0));
BlockPos expand = new BlockPos(getValueFromStringOrDefault(cond, "dx", 0), getValueFromStringOrDefault(cond, "dy", 0), getValueFromStringOrDefault(cond, "dz", 0));
BlockPos blockpos = new BlockPos((int) getValueFromStringOrDefault(cond, "x", 0), (int) getValueFromStringOrDefault(cond, "y", 0), (int) getValueFromStringOrDefault(cond, "z", 0));
BlockPos expand = new BlockPos((int) getValueFromStringOrDefault(cond, "dx", 0), (int) getValueFromStringOrDefault(cond, "dy", 0), (int) getValueFromStringOrDefault(cond, "dz", 0));
BlockPos expanded = blockpos.offset(expand);
BlockPos pos = elem.blockPosition();
@ -338,7 +263,7 @@ public final class Matchables
for (MobEffectInstance effect : fx)
{
int amp = effect.getAmplifier();
String name = Registry.MOB_EFFECT.getKey(effect.getEffect()).toString();
String name = effect.getEffect().getRegisteredName();
if (names.contains(name))
{

View File

@ -1,14 +1,35 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.scripting;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.TagValueOutput;
import tschipp.carryon.Constants;
import tschipp.carryon.common.scripting.CarryOnScript.ScriptObject.ScriptObjectBlock;
import tschipp.carryon.common.scripting.CarryOnScript.ScriptObject.ScriptObjectEntity;
@ -28,13 +49,12 @@ public class ScriptManager
return Optional.empty();
Block block = state.getBlock();
Material material = state.getMaterial();
float hardness = state.getDestroySpeed(level, pos);
float resistance = block.getExplosionResistance();
for (CarryOnScript script : SCRIPTS)
{
if (script.isBlock() && matchesAll(script, block, material, hardness, resistance, tag))
if (script.isBlock() && matchesAll(script, block, hardness, resistance, tag))
return Optional.of(script);
}
@ -49,8 +69,9 @@ public class ScriptManager
float height = entity.getBbHeight();
float width = entity.getBbWidth();
float health = entity instanceof LivingEntity ? ((LivingEntity) entity).getHealth() : 0.0f;
CompoundTag tag = new CompoundTag();
entity.save(tag);
TagValueOutput output = TagValueOutput.createWithContext(new ProblemReporter.ScopedCollector(Constants.LOG), entity.registryAccess());
entity.save(output);
CompoundTag tag = output.buildResult();
for (CarryOnScript script : SCRIPTS)
{
@ -67,7 +88,7 @@ public class ScriptManager
boolean matchname = true;
if(scEntity.typeNameEntity().isPresent())
matchname = entity.getType().equals(Registry.ENTITY_TYPE.get(scEntity.typeNameEntity().get()));
matchname = entity.getType().equals(BuiltInRegistries.ENTITY_TYPE.get(scEntity.typeNameEntity().get()));
boolean matchheight = scEntity.typeHeight().matches(height);
boolean matchwidth = scEntity.typeWidth().matches(width);
boolean matchhealth = scEntity.typeHealth().matches(health);
@ -76,18 +97,17 @@ public class ScriptManager
return matchname && matchheight && matchwidth && matchhealth && matchnbt;
}
private static boolean matchesAll(CarryOnScript script, Block block, Material material, float hardness, float resistance, CompoundTag nbt)
private static boolean matchesAll(CarryOnScript script, Block block, float hardness, float resistance, CompoundTag nbt)
{
ScriptObjectBlock scBlock = script.scriptObject().block();
boolean matchblock = true;
if(scBlock.typeNameBlock().isPresent())
matchblock = block == Registry.BLOCK.get(scBlock.typeNameBlock().get());
matchblock = block == BuiltInRegistries.BLOCK.get(scBlock.typeNameBlock().get()).get().value();
boolean matchnbt = scBlock.typeBlockTag().matches(nbt);
boolean matchmaterial = scBlock.typeMaterial().matches(material);
boolean matchhardness = scBlock.typeHardness().matches(hardness);
boolean matchresistance = scBlock.typeResistance().matches(resistance);
return matchnbt && matchblock && matchmaterial && matchhardness && matchresistance;
return matchnbt && matchblock && matchhardness && matchresistance;
}
}

View File

@ -1,67 +1,69 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.common.scripting;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.FileToIdConverter;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener;
import net.minecraft.util.profiling.ProfilerFiller;
import org.jetbrains.annotations.NotNull;
import tschipp.carryon.Constants;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.networking.clientbound.ClientboundSyncScriptsPacket;
import tschipp.carryon.platform.Services;
import java.util.Collections;
import java.util.Map;
public class ScriptReloadListener extends SimpleJsonResourceReloadListener
public class ScriptReloadListener extends SimpleJsonResourceReloadListener<CarryOnScript>
{
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
public ScriptReloadListener()
{
super(GSON, "carryon/scripts");
super(CarryOnScript.CODEC, FileToIdConverter.json("carryon/scripts"));
}
@Override
protected void apply(Map<ResourceLocation, JsonElement> objects, ResourceManager manager, ProfilerFiller profiler)
protected void apply(Map<Identifier, CarryOnScript> scripts, @NotNull ResourceManager resourceManager, @NotNull ProfilerFiller profilerFiller)
{
ScriptManager.SCRIPTS.clear();
try {
objects.forEach((path, jsonElem) -> {
DataResult<CarryOnScript> res = CarryOnScript.CODEC.parse(JsonOps.INSTANCE, jsonElem);
if(res.result().isPresent())
{
CarryOnScript script = res.result().get();
if (script.isValid())
ScriptManager.SCRIPTS.add(script);
}
else
Constants.LOG.warn("Error while parsing script: " + res.error().get().message());
});
}
catch (Exception e)
{
e.printStackTrace();
}
scripts.forEach((path, script) -> {
if (script.isValid())
ScriptManager.SCRIPTS.add(script);
});
Collections.sort(ScriptManager.SCRIPTS, (s1, s2) -> Long.compare(s2.priority(), s1.priority()));
ScriptManager.SCRIPTS.sort((s1, s2) -> Long.compare(s2.priority(), s1.priority()));
}
public static void syncScriptsWithClient(ServerPlayer player)
{
if (player != null)
{
DataResult<Tag> result = Codec.list(CarryOnScript.CODEC).encodeStart(NbtOps.INSTANCE, ScriptManager.SCRIPTS);
Tag tag = result.getOrThrow(false, s -> {throw new RuntimeException("Error while synching Carry On Scripts: " + s);});
Tag tag = result.getOrThrow(s -> {throw new RuntimeException("Error while synching Carry On Scripts: " + s);});
Services.PLATFORM.sendPacketToPlayer(Constants.PACKET_ID_SYNC_SCRIPTS, new ClientboundSyncScriptsPacket(tag), player);
}

View File

@ -0,0 +1,107 @@
package tschipp.carryon.compat;
import me.shedaniel.clothconfig2.api.ConfigBuilder;
import me.shedaniel.clothconfig2.api.ConfigCategory;
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
import me.shedaniel.clothconfig2.impl.builders.SubCategoryBuilder;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import tschipp.carryon.config.AnnotationData;
import tschipp.carryon.config.BuiltCategory;
import tschipp.carryon.config.BuiltConfig;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
public record ClothConfigCompat(BuiltConfig client, BuiltConfig common, Runnable onSave) {
public static Screen getConfigScreen(BuiltConfig client, BuiltConfig common, Screen parentScreen, Runnable onSave) {
ConfigBuilder builder = ConfigBuilder.create()
.setParentScreen(parentScreen)
.setTitle(Component.translatable("key.category.carryon.key.carry.category"));
buildConfigType(client, builder, "Client Config");
buildConfigType(common, builder, "Common Config");
builder.setSavingRunnable(onSave);
return builder.build();
}
private static void buildConfigType(BuiltConfig cfg, ConfigBuilder builder, String name) {
ConfigCategory configCategory = builder.getOrCreateCategory(Component.literal(name));
buildProperties(cfg, configCategory, builder, null);
}
private static void buildCategory(BuiltCategory category, ConfigCategory categoryBuilder, ConfigBuilder builder) {
ConfigEntryBuilder entryBuilder = builder.entryBuilder();
SubCategoryBuilder subBuilder = entryBuilder.startSubCategory(Component.translatable(category.translation));
buildProperties(category, categoryBuilder, builder, subBuilder);
}
private static void buildProperties(BuiltCategory category, ConfigCategory categoryBuilder, ConfigBuilder builder, @Nullable SubCategoryBuilder subBuilder) {
category.categories.forEach(cat -> {
buildCategory(cat, categoryBuilder, builder);
});
ConfigEntryBuilder entryBuilder = builder.entryBuilder();
category.properties.forEach(propertyData -> {
try {
AnnotationData data = propertyData.getData();
var entry =
switch (data.type()) {
case BOOLEAN ->
entryBuilder.startBooleanToggle(Component.literal(propertyData.getField().getName()), propertyData.getBoolean())
.setTooltip(Component.literal(data.description()))
.setDefaultValue(propertyData.getDefaultBoolean())
.setSaveConsumer((Consumer<Boolean>) propertyData.getSetter())
.build();
case INT ->
entryBuilder.startIntField(Component.literal(propertyData.getField().getName()), propertyData.getInt())
.setTooltip(Component.literal(data.description()))
.setDefaultValue(propertyData.getDefaultInt())
.setMin(data.min())
.setMax(data.max())
.setSaveConsumer((Consumer<Integer>) propertyData.getSetter())
.build();
case DOUBLE ->
entryBuilder.startDoubleField(Component.literal(propertyData.getField().getName()), propertyData.getDouble())
.setTooltip(Component.literal(data.description()))
.setDefaultValue(propertyData.getDefaultDouble())
.setMin(data.minD())
.setMax(data.maxD())
.setSaveConsumer((Consumer<Double>) propertyData.getSetter())
.build();
case STRING_ARRAY ->
entryBuilder.startStrList(Component.literal(propertyData.getField().getName()), List.of(propertyData.getStringArray()))
.setTooltip(Component.literal(data.description()))
.setInsertInFront(true)
.setDefaultValue(List.of(propertyData.getDefaultStringArray()))
.setCellErrorSupplier(str -> str.matches(data.validationRegex()) ? Optional.empty() : Optional.of(Component.literal("Invalid Format")))
.setSaveConsumer((Consumer<List<String>>) propertyData.getSetter())
.build();
default -> null;
};
if(subBuilder == null)
categoryBuilder.addEntry(entry);
else
subBuilder.add(entry);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
if(subBuilder != null)
categoryBuilder.addEntry(subBuilder.build());
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config;
@ -9,7 +29,8 @@ public record AnnotationData(
PropertyType type,
String description,
int min, int max,
double minD, double maxD
double minD, double maxD,
String validationRegex
) {
public static AnnotationData getData(Field field) {
@ -18,7 +39,8 @@ public record AnnotationData(
annotation.type(),
annotation.description(),
annotation.min(), annotation.max(),
annotation.minD(), annotation.maxD()
annotation.minD(), annotation.maxD(),
annotation.validationRegex()
);
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config;
import java.util.ArrayList;
@ -12,9 +32,12 @@ public class BuiltCategory {
public final String categoryDesc;
public final String category;
public BuiltCategory(String categoryDesc, String category) {
public final String translation;
public BuiltCategory(String categoryDesc, String category, String translation) {
this.categoryDesc = categoryDesc;
this.category = category;
this.translation = translation;
}
public Optional<PropertyData> getProperty(String id) {

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config;
public class BuiltConfig extends BuiltCategory {
@ -5,7 +25,7 @@ public class BuiltConfig extends BuiltCategory {
public final String fileName;
public BuiltConfig(String fileName) {
super(null, fileName);
super(null, fileName, "key.carry.category");
this.fileName = fileName;
}
}

View File

@ -1,7 +1,28 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config;
//Many Thanks to ThatGravyBoat for this template!
import net.minecraft.core.HolderLookup;
import tschipp.carryon.client.modeloverride.ModelOverrideHandler;
import tschipp.carryon.common.config.ListHandler;
import tschipp.carryon.common.pickupcondition.PickupConditionHandler;
@ -33,10 +54,10 @@ public class ConfigLoader {
Services.PLATFORM.registerConfig(config);
}
public static void onConfigLoaded() {
public static void onConfigLoaded(HolderLookup.Provider provider) {
ListHandler.initConfigLists();
PickupConditionHandler.initPickupConditions();
ModelOverrideHandler.initModelOverrides();
ModelOverrideHandler.initModelOverrides(provider);
}
public static BuiltCategory buildCategory(String categoryDesc, Object object) throws IllegalAccessException {
@ -45,7 +66,7 @@ public class ConfigLoader {
if (configClass.isAnnotationPresent(Config.class)) {
category = new BuiltConfig(configClass.getAnnotation(Config.class).value());
} else if (configClass.isAnnotationPresent(Category.class)) {
category = new BuiltCategory(categoryDesc, configClass.getAnnotation(Category.class).value());
category = new BuiltCategory(categoryDesc, configClass.getAnnotation(Category.class).value(), configClass.getAnnotation(Category.class).translation());
} else {
throw new IllegalStateException("Config does not contain any @Config annotation or @Category");
}
@ -56,7 +77,7 @@ public class ConfigLoader {
if (type.equals(PropertyType.CATEGORY)) {
category.categories.add(buildCategory(field.getAnnotation(Property.class).description(), field.get(object)));
} else {
category.properties.add(new PropertyData(object, field, AnnotationData.getData(field)));
category.properties.add(new PropertyData(object, field, AnnotationData.getData(field), field.get(object)));
}
}
}

View File

@ -1,15 +1,69 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config;
import java.lang.reflect.Field;
import java.util.function.Consumer;
public record PropertyData(Object fieldClass, Field field, AnnotationData data) {
public class PropertyData {
Object fieldClass;
Field field;
AnnotationData data;
Object defaultValue;
Consumer<?> setter;
public PropertyData(Object fieldClass, Field field, AnnotationData data, Object defaultValue) {
this.fieldClass = fieldClass;
this.field = field;
this.data = data;
this.defaultValue = defaultValue;
}
public Consumer<?> getSetter() {
return setter;
}
public void setSetter(Consumer<?> setter) {
this.setter = setter;
}
public AnnotationData getData() {
return data;
}
public Field getField() {
return field;
}
public Object getFieldClass() {
return fieldClass;
}
public String getId() {
return field().getName();
return field.getName();
}
public boolean getBoolean() throws IllegalAccessException {
return field().getBoolean(fieldClass());
return field.getBoolean(fieldClass);
}
public void setBoolean(boolean _boolean) {
@ -20,8 +74,12 @@ public record PropertyData(Object fieldClass, Field field, AnnotationData data)
}
}
public boolean getDefaultBoolean() {
return (boolean)defaultValue;
}
public int getInt() throws IllegalAccessException {
return field().getInt(fieldClass());
return field.getInt(fieldClass);
}
public void setInt(int _int) {
@ -32,8 +90,12 @@ public record PropertyData(Object fieldClass, Field field, AnnotationData data)
}
}
public int getDefaultInt() {
return (int)defaultValue;
}
public double getDouble() throws IllegalAccessException {
return field().getDouble(fieldClass());
return field.getDouble(fieldClass);
}
public void setDouble(double _double) {
@ -44,8 +106,12 @@ public record PropertyData(Object fieldClass, Field field, AnnotationData data)
}
}
public double getDefaultDouble() {
return (double)defaultValue;
}
public String[] getStringArray() throws IllegalAccessException {
return (String[])field().get(fieldClass());
return (String[])field.get(fieldClass);
}
public void setStringArray(String[] arr)
@ -56,4 +122,8 @@ public record PropertyData(Object fieldClass, Field field, AnnotationData data)
//Ignore
}
}
public String[] getDefaultStringArray() {
return (String[])defaultValue;
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config;
public enum PropertyType {

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config.annotations;
import java.lang.annotation.ElementType;
@ -9,4 +29,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface Category {
String value();
String translation() default "";
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config.annotations;
import java.lang.annotation.ElementType;

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config.annotations;
import tschipp.carryon.config.PropertyType;
@ -12,7 +32,6 @@ import java.lang.annotation.Target;
public @interface Property {
PropertyType type();
String description();
@ -21,4 +40,6 @@ public @interface Property {
double minD() default Double.MIN_VALUE;
double maxD() default Double.MAX_VALUE;
String validationRegex() default ".*";
}

View File

@ -0,0 +1,29 @@
package tschipp.carryon.mixin;
import net.minecraft.client.entity.ClientAvatarEntity;
import net.minecraft.client.model.player.PlayerModel;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.EntityRendererProvider.Context;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.renderer.entity.player.AvatarRenderer;
import net.minecraft.client.renderer.entity.state.AvatarRenderState;
import net.minecraft.world.entity.Avatar;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import tschipp.carryon.client.render.CarryingItemRenderLayer;
@Mixin(AvatarRenderer.class)
public abstract class AvatarRendererMixin<AvatarlikeEntity extends Avatar & ClientAvatarEntity> extends LivingEntityRenderer<AvatarlikeEntity, AvatarRenderState, PlayerModel> {
public AvatarRendererMixin(Context context, PlayerModel model, float shadowRadius) {
super(context, model, shadowRadius);
}
@Inject(method = "<init>(Lnet/minecraft/client/renderer/entity/EntityRendererProvider$Context;Z)V", at = @At("RETURN"))
public void init(EntityRendererProvider.Context context, boolean slim, CallbackInfo info) {
//Player
this.addLayer(new CarryingItemRenderLayer<>(this));
}
}

View File

@ -1,5 +1,26 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
@ -27,6 +48,13 @@ public abstract class EntityMixin
@Shadow
public boolean hasPassenger(Entity pEntity) {throw new IllegalStateException("EntityMixin application failed");}
@ModifyExpressionValue(method = "startRiding(Lnet/minecraft/world/entity/Entity;ZZ)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;canSerialize()Z"))
private boolean onStartRidingCheck(boolean original, Entity entity, boolean force) {
if (force && entity instanceof Player) return true;
return original;
}
@Shadow public abstract void onPassengerTurned(Entity $$0);
@Inject(method = "positionRider(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity$MoveFunction;)V", at = @At("HEAD"), cancellable = true)
@ -65,7 +93,7 @@ public abstract class EntityMixin
@Inject(method = "onPassengerTurned(Lnet/minecraft/world/entity/Entity;)V", at = @At("HEAD"))
private void onPassengerTurned(Entity toUpdate, CallbackInfo ci)
{
if((Object)this instanceof Player thisPlayer && toUpdate instanceof Player otherPlayer)
if((Object)this instanceof Player thisPlayer && toUpdate instanceof Player)
{
CarryOnData carry = CarryOnDataManager.getCarryData(thisPlayer);
if(carry.isCarrying(CarryType.PLAYER)) {

View File

@ -0,0 +1,36 @@
package tschipp.carryon.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import tschipp.carryon.client.render.CarryRenderHelper;
import tschipp.carryon.client.render.ICarryOnRenderState;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.common.carry.CarryOnDataManager;
@Mixin(EntityRenderer.class)
public class EntityRendererMixin {
@Inject(at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;extractRenderState(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/client/renderer/entity/state/EntityRenderState;F)V",
shift = At.Shift.AFTER
), method = "createRenderState(Lnet/minecraft/world/entity/Entity;F)Lnet/minecraft/client/renderer/entity/state/EntityRenderState;")
private void onCreateRenderState(Entity entity, float $$1, CallbackInfoReturnable<EntityRenderState> cir, @Local(ordinal = 0) EntityRenderState state) {
if (entity instanceof Player player) {
CarryOnData carry = CarryOnDataManager.getCarryData(player);
ICarryOnRenderState carryOnRenderState = (ICarryOnRenderState) state;
carryOnRenderState.setCarryOnData(carry);
carryOnRenderState.setRenderWidth(CarryRenderHelper.getRenderWidth(player));
carryOnRenderState.setPlayer(player);
}
}
}

View File

@ -1,9 +1,28 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.client.renderer.entity.state.HumanoidRenderState;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -12,9 +31,8 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import tschipp.carryon.Constants;
import tschipp.carryon.client.render.CarryRenderHelper;
import tschipp.carryon.client.render.ICarryOnRenderState;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.common.carry.CarryOnDataManager;
import tschipp.carryon.common.scripting.CarryOnScript.ScriptRender;
@Mixin(HumanoidModel.class)
@ -26,20 +44,20 @@ public class HumanoidModelMixin {
@Shadow
public ModelPart leftArm;
@Inject(at = @At("RETURN"), method = "setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V")
private void onSetupAnimations(LivingEntity living, float f1, float f2, float f3, float f4, float f5, CallbackInfo ci)
@Inject(at = @At("RETURN"), method = "setupAnim(Lnet/minecraft/client/renderer/entity/state/HumanoidRenderState;)V")
private void onSetupAnimations(HumanoidRenderState state, CallbackInfo ci)
{
if(living instanceof Player player && Constants.CLIENT_CONFIG.renderArms)
if(state instanceof ICarryOnRenderState carryOnRenderState && Constants.CLIENT_CONFIG.renderArms)
{
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if(carry.isCarrying() && !player.isVisuallySwimming() && !player.isFallFlying())
CarryOnData carry = carryOnRenderState.getCarryOnData();
if(carry != null && carry.isCarrying() && !state.isVisuallySwimming && !state.isFallFlying)
{
boolean sneaking = !player.getAbilities().flying && player.isShiftKeyDown() || player.isCrouching();
boolean sneaking = state.isCrouching;
float x = 1.0f + (sneaking ? 0.2f : 0.0f) + (carry.isCarrying(CarryOnData.CarryType.BLOCK) ? 0.0f : 0.3f);
float z = 0.05f;
float width = CarryRenderHelper.getRenderWidth(player);
float width = carryOnRenderState.getRenderWidth();
float offset = Math.min((width - 1) / 1.5f, 0.2f);
if(carry.getActiveScript().isPresent())

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
@ -9,15 +29,17 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Blocks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.common.carry.CarryOnDataManager;
@Mixin(Inventory.class)
public class InventoryMixin
{
@Unique
private static final ItemStack DUMMY_STACK = new ItemStack(Blocks.COBBLESTONE, 1);
@Shadow
@ -40,7 +62,7 @@ public class InventoryMixin
return original.call(instance, slot);
}
@Inject(method = "setPickedItem(Lnet/minecraft/world/item/ItemStack;)V", at = @At("HEAD"), cancellable = true)
@Inject(method = "addAndPickItem(Lnet/minecraft/world/item/ItemStack;)V", at = @At("HEAD"), cancellable = true)
private void onPickBlock(CallbackInfo info)
{
if(CarryOnDataManager.getCarryData(player).isCarrying())
@ -54,10 +76,11 @@ public class InventoryMixin
info.cancel();
}
@Inject(method = "swapPaint(D)V", at = @At("HEAD"), cancellable = true)
private void onSwapPaint(double direction, CallbackInfo info)
@Inject(method = "setSelectedSlot(I)V", at = @At("HEAD"), cancellable = true)
private void onSwapPaint(int slot, CallbackInfo info)
{
if(CarryOnDataManager.getCarryData(player).isCarrying())
CarryOnData data = CarryOnDataManager.getCarryData(player);
if(data.isCarrying() && data.getSelected() != slot)
info.cancel();
}
}

View File

@ -1,19 +1,51 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;
import com.llamalad7.mixinextras.injector.WrapWithCondition;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.player.Inventory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import tschipp.carryon.common.carry.CarryOnDataManager;
@Mixin(Minecraft.class)
public class MinecraftMixin
{
@WrapWithCondition(method = "handleKeybinds()V", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/player/Inventory;selected:I", ordinal = 0, opcode = 181)) //Opcode for PUTFIELD
private boolean allowSlotSelection(Inventory inv,int slot)
{
return !CarryOnDataManager.getCarryData(inv.player).isCarrying();
}
public class MinecraftMixin {
@WrapWithCondition(
method = "handleKeybinds()V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/player/Inventory;setSelectedSlot(I)V",
ordinal = 0
)
)
private boolean allowSlotSelection(Inventory inv, int slot) {
boolean carrying = CarryOnDataManager.getCarryData(inv.player).isCarrying();
// Allow if not carrying
if (!carrying) return true;
// Block only if trying to switch away
return inv.getSelectedSlot() == slot;
}
}

View File

@ -1,44 +1,68 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.ValueInput;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.common.carry.CarryOnData.CarryType;
import tschipp.carryon.common.carry.CarryOnDataManager;
import java.util.Optional;
@Mixin(Player.class)
public abstract class PlayerMixin extends LivingEntity {
public abstract class PlayerMixin extends LivingEntity {
private PlayerMixin(EntityType<? extends LivingEntity> type, Level level) {
super(type, level);
}
@Inject(method = "defineSynchedData()V", at = @At("RETURN"))
private void onDefineSynchedData(CallbackInfo info) {
this.entityData.define(CarryOnDataManager.CARRY_DATA_KEY, new CompoundTag());
//We leave this in here to ensure cross-compatibility if world are upgraded from <1.21.8. Should be removed in the future.
@Inject(method = "readAdditionalSaveData(Lnet/minecraft/world/level/storage/ValueInput;)V", at = @At("RETURN"))
private void onReadAdditionalSaveData(ValueInput input, CallbackInfo ci)
{
Optional<CarryOnData> res = input.read("CarryOnData", CarryOnData.CODEC);
res.ifPresent(data -> CarryOnDataManager.setCarryData((Player)((Object)this), data));
}
@Inject(method = "addAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("RETURN"))
private void onAddAdditionalSaveData(CompoundTag tag, CallbackInfo info)
{
CarryOnData carry = CarryOnDataManager.getCarryData((Player)(Object)this);
tag.put("CarryOnData", carry.getNbt());
}
@Inject(method = "readAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V", at = @At("RETURN"))
private void onReadAdditionalSaveData(CompoundTag tag, CallbackInfo info)
{
if (tag.contains("CarryOnData")) {
CarryOnData data = new CarryOnData(tag.getCompound("CarryOnData"));
CarryOnDataManager.setCarryData((Player) (Object) this, data);
@Override
public void stopRiding() {
Entity entity = this.getVehicle();
if (entity instanceof Player && entity.getPassengers().size() < 2){
CarryOnData carry = CarryOnDataManager.getCarryData((Player) entity);
if (carry.getType() == CarryType.PLAYER){
carry.clear();
((Player) entity).removeEffect(MobEffects.SLOWNESS);
}
}
super.stopRiding();
}
}

View File

@ -0,0 +1,56 @@
package tschipp.carryon.mixin;
import net.minecraft.client.renderer.entity.state.HumanoidRenderState;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import tschipp.carryon.client.render.ICarryOnRenderState;
import tschipp.carryon.common.carry.CarryOnData;
@Mixin(HumanoidRenderState.class)
public class PlayerRenderStateMixin implements ICarryOnRenderState {
@Unique
public CarryOnData carryOnData = null;
@Unique
public float renderWidth = 0f;
@Unique
public Player player = null;
@Unique
@Override
public CarryOnData getCarryOnData() {
return carryOnData;
}
@Unique
@Override
public void setCarryOnData(CarryOnData data) {
carryOnData = data;
}
@Unique
@Override
public float getRenderWidth() {
return renderWidth;
}
@Unique
@Override
public void setRenderWidth(float val) {
renderWidth = val;
}
@Override
public Player getPlayer() {
return player;
}
@Override
public void setPlayer(Player player) {
this.player = player;
}
}

View File

@ -1,11 +1,29 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.networking;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.world.entity.player.Player;
public abstract class PacketBase
{
public abstract void toBytes(FriendlyByteBuf buf);
public interface PacketBase extends CustomPacketPayload {
public abstract void handle(Player player);
void handle(Player player);
}

View File

@ -0,0 +1,59 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.networking.clientbound;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.Constants;
import tschipp.carryon.networking.PacketBase;
public record ClientboundStartRidingOtherPlayerPacket(int mount, int rider, boolean ride) implements PacketBase
{
public static final StreamCodec<RegistryFriendlyByteBuf, ClientboundStartRidingOtherPlayerPacket> CODEC = StreamCodec.composite(
ByteBufCodecs.INT, ClientboundStartRidingOtherPlayerPacket::mount,
ByteBufCodecs.INT, ClientboundStartRidingOtherPlayerPacket::rider,
ByteBufCodecs.BOOL, ClientboundStartRidingOtherPlayerPacket::ride,
ClientboundStartRidingOtherPlayerPacket::new
);
public static final Type<ClientboundStartRidingOtherPlayerPacket> TYPE = new Type<>(Constants.PACKET_ID_START_RIDING_OTHER);
@Override
public void handle(Player player)
{
Entity mount = player.level().getEntity(this.mount);
Entity rider = player.level().getEntity(this.rider);
if(mount != null && rider != null)
if(ride)
rider.startRiding(mount, true,true);
else
rider.stopRiding();
}
@Override
public Type<ClientboundStartRidingOtherPlayerPacket> type() {
return TYPE;
}
}

View File

@ -1,42 +1,57 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.networking.clientbound;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.Constants;
import tschipp.carryon.networking.PacketBase;
public class ClientboundStartRidingPacket extends PacketBase
public record ClientboundStartRidingPacket(int iden, boolean ride) implements PacketBase
{
int entityId;
boolean ride;
public static final StreamCodec<RegistryFriendlyByteBuf, ClientboundStartRidingPacket> CODEC = StreamCodec.composite(
ByteBufCodecs.INT, ClientboundStartRidingPacket::iden,
ByteBufCodecs.BOOL, ClientboundStartRidingPacket::ride,
ClientboundStartRidingPacket::new
);
public ClientboundStartRidingPacket(FriendlyByteBuf buf)
{
this.entityId = buf.readInt();
this.ride = buf.readBoolean();
}
public ClientboundStartRidingPacket(int id, boolean ride)
{
this.entityId = id;
this.ride = ride;
}
@Override
public void toBytes(FriendlyByteBuf buf)
{
buf.writeInt(entityId);
buf.writeBoolean(ride);
}
public static final CustomPacketPayload.Type<ClientboundStartRidingPacket> TYPE = new Type<>(Constants.PACKET_ID_START_RIDING);
@Override
public void handle(Player player)
{
Entity otherPlayer = player.level.getEntity(this.entityId);
Entity otherPlayer = player.level().getEntity(this.iden);
if(otherPlayer != null)
if(ride)
otherPlayer.startRiding(player);
else
otherPlayer.stopRiding();
}
@Override
public Type<ClientboundStartRidingPacket> type() {
return TYPE;
}
}

View File

@ -1,46 +1,61 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.networking.clientbound;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.Constants;
import tschipp.carryon.common.scripting.CarryOnScript;
import tschipp.carryon.common.scripting.ScriptManager;
import tschipp.carryon.networking.PacketBase;
import java.util.List;
public class ClientboundSyncScriptsPacket extends PacketBase
public record ClientboundSyncScriptsPacket(Tag serialized) implements PacketBase
{
private Tag serialized;
public static final StreamCodec<RegistryFriendlyByteBuf, ClientboundSyncScriptsPacket> CODEC = StreamCodec.composite(
ByteBufCodecs.TAG, ClientboundSyncScriptsPacket::serialized,
ClientboundSyncScriptsPacket::new
);
public ClientboundSyncScriptsPacket(FriendlyByteBuf buf)
{
this.serialized = buf.readNbt().get("data");
}
public ClientboundSyncScriptsPacket(Tag serialized)
{
this.serialized = serialized;
}
@Override
public void toBytes(FriendlyByteBuf buf)
{
CompoundTag tag = new CompoundTag();
tag.put("data", serialized);
buf.writeNbt(tag);
}
public static final CustomPacketPayload.Type<ClientboundSyncScriptsPacket> TYPE = new Type<>(Constants.PACKET_ID_SYNC_SCRIPTS);
@Override
public void handle(Player player)
{
DataResult<List<CarryOnScript>> res = Codec.list(CarryOnScript.CODEC).parse(NbtOps.INSTANCE, serialized);
List<CarryOnScript> scripts = res.getOrThrow(false, (s) -> {throw new RuntimeException("Failed deserializing carry on scripts on the client: " + s);});
List<CarryOnScript> scripts = res.getOrThrow((s) -> {throw new RuntimeException("Failed deserializing carry on scripts on the client: " + s);});
ScriptManager.SCRIPTS.clear();
ScriptManager.SCRIPTS.addAll(scripts);
}
@Override
public Type<ClientboundSyncScriptsPacket> type() {
return TYPE;
}
}

View File

@ -1,31 +1,43 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.networking.serverbound;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.Constants;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.common.carry.CarryOnDataManager;
import tschipp.carryon.networking.PacketBase;
public class ServerboundCarryKeyPressedPacket extends PacketBase
public record ServerboundCarryKeyPressedPacket(boolean pressed) implements PacketBase
{
boolean pressed;
public static final StreamCodec<RegistryFriendlyByteBuf, ServerboundCarryKeyPressedPacket> CODEC = StreamCodec.composite(
ByteBufCodecs.BOOL, ServerboundCarryKeyPressedPacket::pressed,
ServerboundCarryKeyPressedPacket::new
);
public ServerboundCarryKeyPressedPacket(FriendlyByteBuf buf)
{
this.pressed = buf.readBoolean();
}
public ServerboundCarryKeyPressedPacket(boolean pressed)
{
this.pressed = pressed;
}
@Override
public void toBytes(FriendlyByteBuf buf)
{
buf.writeBoolean(pressed);
}
public static final CustomPacketPayload.Type<ServerboundCarryKeyPressedPacket> TYPE = new Type<>(Constants.PACKET_ID_KEY_PRESSED);
@Override
public void handle(Player player)
@ -34,4 +46,9 @@ public class ServerboundCarryKeyPressedPacket extends PacketBase
carry.setKeyPressed(this.pressed);
CarryOnDataManager.setCarryData(player, carry);
}
@Override
public Type<ServerboundCarryKeyPressedPacket> type() {
return TYPE;
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.platform;
import tschipp.carryon.Constants;

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.platform.services;
import net.minecraft.world.entity.player.Player;

View File

@ -1,14 +1,37 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.platform.services;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.config.BuiltConfig;
import tschipp.carryon.networking.PacketBase;
import java.util.function.BiConsumer;
import java.util.function.Function;
public interface IPlatformHelper {
@ -36,12 +59,21 @@ public interface IPlatformHelper {
void registerConfig(BuiltConfig cfg);
<T extends PacketBase> void registerServerboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler);
<T extends PacketBase, B extends FriendlyByteBuf> void registerServerboundPacket(CustomPacketPayload.Type<T> type, Class<T> clazz, StreamCodec<B, T> codec, BiConsumer<T, Player> handler, Object... args);
<T extends PacketBase> void registerClientboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler);
<T extends PacketBase, B extends FriendlyByteBuf> void registerClientboundPacket(CustomPacketPayload.Type<T> type, Class<T> clazz, StreamCodec<B, T> codec, BiConsumer<T, Player> handler, Object... args);
void sendPacketToServer(ResourceLocation id, PacketBase packet);
void sendPacketToServer(Identifier id, PacketBase packet);
void sendPacketToPlayer(ResourceLocation id, PacketBase packet, ServerPlayer player);
void sendPacketToPlayer(Identifier id, PacketBase packet, ServerPlayer player);
default void sendPacketToAllPlayers(Identifier id, PacketBase packet, ServerLevel level) {
for(ServerPlayer p : level.players())
sendPacketToPlayer(id, packet, p);
}
CarryOnData getCarryData(Player player);
void setCarryData(Player player, CarryOnData data);
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.utils;
public class StringHelper

View File

@ -0,0 +1,16 @@
{
"carryon.category.settings": "Einstellungen",
"carryon.category.blacklist": "Blacklist",
"carryon.category.modeloverrides": "Modellüberschreibungen (Fortgeschritten)",
"carryon.category.custompickupconditions": "Benutzerdefinierte Bedingungen (Fortgeschritten)",
"carryon.category.whitelist": "Whitelist",
"carryon.general.modeloverrides.modeloverrides": "Modellüberschreibungen",
"carryon.general.blacklist.forbiddenentities": "Entitäten, die Spieler nicht aufheben dürfen",
"carryon.general.blacklist.forbiddentiles": "Blöcke, die Spieler nicht aufheben dürfen",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "Benutzerdefinierte Bedingungen für Blöcke",
"carryon.category.custompickupconditions.custompickupconditionsentities": "Benutzerdefinierte Bedingungen für Entitäten",
"key.carry.desc": "Carry",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -12,5 +12,5 @@
"carryon.category.custompickupconditions.custompickupconditionsentities": "suoᴉʇᴉpuoƆ dnʞɔᴉԀ ʎʇᴉʇuƎ ɯoʇsnƆ",
"key.carry.desc": "ʎɹɹɐƆ",
"key.carry.category": "uO ʎɹɹɐƆ"
"key.category.carryon.key.carry.category": "uO ʎɹɹɐƆ"
}

View File

@ -12,5 +12,5 @@
"carryon.category.custompickupconditions.custompickupconditionsentities": "Custom Entity Pickup Conditions",
"key.carry.desc": "Carry",
"key.carry.category": "Carry On"
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -0,0 +1,16 @@
{
"carryon.category.settings": "Configuraciones",
"carryon.category.blacklist": "Lista Negra",
"carryon.category.modeloverrides": "Reemplazos de Modelos (Avanzado)",
"carryon.category.custompickupconditions": "Condiciones Personalizadas de Recogida (Avanzado)",
"carryon.category.whitelist": "Lista Blanca",
"carryon.general.modeloverrides.modeloverrides": "Reemplazos de Modelos",
"carryon.general.blacklist.forbiddenentities": "Entidades que el jugador no puede levantar",
"carryon.general.blacklist.forbiddentiles": "Bloques que el jugador no puede levantar",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "Condiciones Personalizadas de Recogida de Bloques",
"carryon.category.custompickupconditions.custompickupconditionsentities": "Condiciones Personalizadas de Recogida de Entidades",
"key.carry.desc": "Cargar",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -0,0 +1,16 @@
{
"carryon.category.settings": "Ajustes",
"carryon.category.blacklist": "Lista Negra",
"carryon.category.modeloverrides": "Reemplazos de Modelo (Avanzado)",
"carryon.category.custompickupconditions": "Condiciones Personalizadas para Recoger (Avanzado)",
"carryon.category.whitelist": "Lista Blanca",
"carryon.general.modeloverrides.modeloverrides": "Reemplazos de Modelo",
"carryon.general.blacklist.forbiddenentities": "Entidades que el jugador no puede recoger",
"carryon.general.blacklist.forbiddentiles": "Bloques que el jugador no puede recoger",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "Condiciones Personalizadas para Recoger Bloques",
"carryon.category.custompickupconditions.custompickupconditionsentities": "Condiciones Personalizadas para Recoger Entidades",
"key.carry.desc": "Recoger",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -12,5 +12,5 @@
"carryon.category.custompickupconditions.custompickupconditionsentities": "Customizar condiciones para recoger entidades",
"key.carry.desc": "Agarrar",
"key.carry.category": "Carry On"
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -1,16 +1,16 @@
{
"carryon.category.settings": "Paramètres",
"carryon.category.blacklist": "Liste noire",
"carryon.category.modeloverrides": "Modèle de Remplacement (Avancé)",
"carryon.category.custompickupconditions": "Conditions de ramassage personalisés (Avancé)",
"carryon.category.whitelist": "Liste blanche",
"carryon.category.settings": "Paramètres",
"carryon.category.blacklist": "Liste noire",
"carryon.category.modeloverrides": "Modèle de Remplacement (Avancé)",
"carryon.category.custompickupconditions": "Conditions de ramassage personalisés (Avancé)",
"carryon.category.whitelist": "Liste blanche",
"carryon.general.modeloverrides.modeloverrides": "Modèle de Remplacement",
"carryon.general.blacklist.forbiddenentities": "Entités que le joueur ne peut pas saisir",
"carryon.general.blacklist.forbiddentiles": "Blocs que le joueur ne peut pas saisir",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "Conditions de ramassage de blocs personalisés",
"carryon.category.custompickupconditions.custompickupconditionsentities": "Conditions de ramassage d'entités personalisés",
"carryon.general.modeloverrides.modeloverrides": "Modèle de Remplacement",
"carryon.general.blacklist.forbiddenentities": "Entités que le joueur ne peut pas saisir",
"carryon.general.blacklist.forbiddentiles": "Blocs que le joueur ne peut pas saisir",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "Conditions de ramassage de blocs personalisés",
"carryon.category.custompickupconditions.custompickupconditionsentities": "Conditions de ramassage d'entités personalisés",
"key.carry.desc": "Saisir",
"key.carry.category": "Carry On"
"key.carry.desc": "Saisir",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -0,0 +1,16 @@
{
"carryon.category.settings": "Beállítások",
"carryon.category.blacklist": "Feketelista",
"carryon.category.modeloverrides": "Model felülírások (Fejlett)",
"carryon.category.custompickupconditions": "Egyedi felvételi feltételek (Fejlett)",
"carryon.category.whitelist": "Fehérlista",
"carryon.general.modeloverrides.modeloverrides": "Model felülírások",
"carryon.general.blacklist.forbiddenentities": "Entitások amiket a játékos nem vehet fel",
"carryon.general.blacklist.forbiddentiles": "Blokkok amiket a játékos nem vehet fel",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "Egyedi blokk felvételi feltételek",
"carryon.category.custompickupconditions.custompickupconditionsentities": "Egyedi entitás felvételi feltételek",
"key.carry.desc": "Cipelés",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -12,5 +12,5 @@
"carryon.category.custompickupconditions.custompickupconditionsentities": "Condizioni di prelievo entità personalizzate",
"key.carry.desc": "Afferra",
"key.carry.category": "Carry On Mod"
"key.category.carryon.key.carry.category": "Carry On Mod"
}

View File

@ -0,0 +1,16 @@
{
"carryon.category.settings": "設定",
"carryon.category.blacklist": "ブラックリスト",
"carryon.category.modeloverrides": "モデルの上書き(上級)",
"carryon.category.custompickupconditions": "カスタム持ち上げ条件(上級)",
"carryon.category.whitelist": "ホワイトリスト",
"carryon.general.modeloverrides.modeloverrides": "モデルの上書き",
"carryon.general.blacklist.forbiddenentities": "プレイヤーが持ち上げられないエンティティ",
"carryon.general.blacklist.forbiddentiles": "プレーヤーが持ち上げられないブロック",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "カスタムブロック持ち上げ条件",
"carryon.category.custompickupconditions.custompickupconditionsentities": "カスタムエンティティ持ち上げ条件",
"key.carry.desc": "Carry",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -1,16 +1,16 @@
{
"carryon.category.settings": "설정",
"carryon.category.blacklist": "블랙리스트",
"carryon.category.modeloverrides": "모델 오버라이딩 (고급)",
"carryon.category.custompickupconditions": "커스텀 들기 컨디션 (고급)",
"carryon.category.modeloverrides": "모델 재정의 (고급)",
"carryon.category.custompickupconditions": "맞춤형 들기 조건 (고급)",
"carryon.category.whitelist": "화이트리스트",
"carryon.general.modeloverrides.modeloverrides": "모델 오버라이딩",
"carryon.general.blacklist.forbiddenentities": "플레이어가 들 수 없는 엔티티",
"carryon.general.modeloverrides.modeloverrides": "모델 재정의",
"carryon.general.blacklist.forbiddenentities": "플레이어가 들 수 없는 개체",
"carryon.general.blacklist.forbiddentiles": "플레이어가 들 수 없는 블록",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "커스텀 블록 들기 컨디션",
"carryon.category.custompickupconditions.custompickupconditionsentities": "커스텀 엔티티 들기 컨디션",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "맞춤형 블록 들기 조건",
"carryon.category.custompickupconditions.custompickupconditionsentities": "맞춤형 개체 들기 조건",
"key.carry.desc": "들고 나르기",
"key.carry.category": "Carry On"
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -12,5 +12,5 @@
"carryon.category.custompickupconditions.custompickupconditionsentities": "Пользовательские условия поднятия сущности",
"key.carry.desc": "Поднять",
"key.carry.category": "Carry On"
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -0,0 +1,17 @@
{
"__comment__": "Translated by @alpeerkaraca",
"carryon.category.settings": "Ayarlar",
"carryon.category.blacklist": "Kara Liste",
"carryon.category.modeloverrides": "Üzerine Yazılan Modeller (Gelişmiş)",
"carryon.category.custompickupconditions": "Özel Yerden Alma Durumları (Gelişmiş)",
"carryon.category.whitelist": "Beyaz Liste",
"carryon.general.modeloverrides.modeloverrides": "Modellerin Üzerine Yaz",
"carryon.general.blacklist.forbiddenentities": "Oyuncunun Alamayacağı Varlıklar",
"carryon.general.blacklist.forbiddentiles": "Oyuncunun Alamayacağı Bloklar",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "Özel Blok Alma Durumları",
"carryon.category.custompickupconditions.custompickupconditionsentities": "Özel Varlık Alma Durumları",
"key.carry.desc": "Taşı",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -0,0 +1,16 @@
{
"carryon.category.settings": "Налаштування",
"carryon.category.blacklist": "Чорний список",
"carryon.category.modeloverrides": "Перевизначення моделей (Розширені)",
"carryon.category.custompickupconditions": "Користувацькі умови підбору (Розширені)",
"carryon.category.whitelist": "Білий список",
"carryon.general.modeloverrides.modeloverrides": "Перевизначення моделей",
"carryon.general.blacklist.forbiddenentities": "Сутності, які гравець не може підібрати",
"carryon.general.blacklist.forbiddentiles": "Блоки, які гравець не може підібрати",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "Користувацькі умови підбору блоків",
"carryon.category.custompickupconditions.custompickupconditionsentities": "Користувацькі умови підбору сутностей",
"key.carry.desc": "Нести",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -0,0 +1,16 @@
{
"carryon.category.settings": "设置",
"carryon.category.blacklist": "黑名单",
"carryon.category.modeloverrides": "模型覆盖(高级设置)",
"carryon.category.custompickupconditions": "自定义抱起条件(高级设置)",
"carryon.category.whitelist": "白名单",
"carryon.general.modeloverrides.modeloverrides": "模型覆盖",
"carryon.general.blacklist.forbiddenentities": "玩家不能抱起的实体",
"carryon.general.blacklist.forbiddentiles": "玩家不能抱起的方块",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "自定义抱起方块条件",
"carryon.category.custompickupconditions.custompickupconditionsentities": "自定义抱起实体条件",
"key.carry.desc": "抱起",
"key.category.carryon.key.carry.category": "搬运"
}

View File

@ -0,0 +1,16 @@
{
"carryon.category.settings": "設定",
"carryon.category.blacklist": "黑名單",
"carryon.category.modeloverrides": "模型覆蓋(進階)",
"carryon.category.custompickupconditions": "自訂拾取條件(進階)",
"carryon.category.whitelist": "白名單",
"carryon.general.modeloverrides.modeloverrides": "模型覆蓋",
"carryon.general.blacklist.forbiddenentities": "玩家無法拾取的實體",
"carryon.general.blacklist.forbiddentiles": "玩家無法拾取的方塊",
"carryon.category.custompickupconditions.custompickupconditionsblocks": "自訂方塊拾取條件",
"carryon.category.custompickupconditions.custompickupconditionsentities": "自訂實體拾取條件",
"key.carry.desc": "攜帶",
"key.category.carryon.key.carry.category": "Carry On"
}

View File

@ -2,15 +2,18 @@
"required": true,
"minVersion": "0.8",
"package": "tschipp.carryon.mixin",
"compatibilityLevel": "JAVA_17",
"compatibilityLevel": "JAVA_21",
"mixins": [
"EntityMixin",
"InventoryMixin",
"PlayerMixin"
],
"client": [
"AvatarRendererMixin",
"EntityRendererMixin",
"HumanoidModelMixin",
"MinecraftMixin"
"MinecraftMixin",
"PlayerRenderStateMixin"
],
"server": [
],
@ -18,5 +21,5 @@
"injectors": {
"defaultRequire": 1
},
"refmap": "${refmap_target}refmap.json"
"refmap": "${mod_id}.refmap.json"
}

View File

@ -1,6 +1,6 @@
{
"pack": {
"description": "${mod_name}",
"pack_format": 8
"pack_format": 34
}
}

View File

@ -1,36 +1,48 @@
plugins {
id 'fabric-loom' version '0.12-SNAPSHOT'
id 'maven-publish'
id 'idea'
id 'multiloader-loader'
id 'fabric-loom' version "${loom_version}"
}
archivesBaseName = "${mod_id}-fabric-${minecraft_version}"
apply from: 'https://raw.githubusercontent.com/MinecraftModDevelopment/Gradle-Collection/22e7d543a18cd30675277fbfa3669e3d9e206010/generic/secrets.gradle'
if (project.hasProperty('secretFile')) {
loadSecrets(new File((String) findProperty('secretFile')))
}
if (System.getenv('BUILD_NUMBER') != null) {
version += "." + System.getenv('BUILD_NUMBER')
}
repositories {
maven {
name = "Shedaniel"
url "https://maven.shedaniel.me/"
}
maven { url 'https://jitpack.io' }
maven {
name = "Terraformers"
url = "https://maven.terraformersmc.com/"
}
}
dependencies {
minecraft "com.mojang:minecraft:${minecraft_version}"
mappings loom.officialMojangMappings()
mappings loom.layered() {
officialMojangMappings()
parchment("org.parchmentmc.data:parchment-${parchment_mappings_fabric}@zip")
}
modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}"
implementation group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1'
implementation project(":Common")
include implementation("com.github.LlamaLad7:MixinExtras:${mixinextras_version}")
annotationProcessor("com.github.LlamaLad7:MixinExtras:${mixinextras_version}")
modApi("me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}") {
exclude(group: "net.fabricmc.fabric-api")
}
modApi "com.terraformersmc:modmenu:17.0.0-beta.1"
}
loom {
def aw = project(':Common').file("src/main/resources/${mod_id}.accesswidener")
if (aw.exists()) {
accessWidenerPath.set(aw)
}
mixin {
defaultRefmapName.set("${mod_id}.refmap.json")
}
runs {
client {
client()
@ -46,41 +58,3 @@ loom {
}
}
}
var refmap_target = archivesBaseName + "-"
processResources {
from project(":Common").sourceSets.main.resources
inputs.property "version", project.version
inputs.property "refmap_target", refmap_target
filesMatching("fabric.mod.json") {
expand "version": project.version
}
filesMatching("carryon.mixins.json") {
expand "refmap_target": refmap_target
}
}
tasks.withType(JavaCompile) {
source(project(":Common").sourceSets.main.allSource)
}
publishing {
publications {
mavenJava(MavenPublication) {
groupId project.group
artifactId project.archivesBaseName
version project.version
from components.java
}
}
repositories {
maven {
url "file://" + System.getenv("local_maven")
}
}
}

View File

@ -1,18 +1,35 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.client.keybinds.CarryOnKeybinds;
import tschipp.carryon.events.ClientEvents;
import tschipp.carryon.networking.PacketBase;
import java.util.function.BiConsumer;
import java.util.function.Function;
public class CarryOnFabricClientMod implements ClientModInitializer
{
@ -21,22 +38,19 @@ public class CarryOnFabricClientMod implements ClientModInitializer
{
CarryOnKeybinds.registerKeybinds(KeyBindingHelper::registerKeyBinding);
ClientEvents.registerEvents();
CarryOnCommon.registerClientPackets();
CarryOnCommon.registerClientPackets(true);
}
public static void sendPacketToServer(ResourceLocation id, PacketBase packet)
public static void sendPacketToServer(PacketBase packet)
{
FriendlyByteBuf buf = PacketByteBufs.create();
packet.toBytes(buf);
ClientPlayNetworking.send(id, buf);
ClientPlayNetworking.send(packet);
}
public static <T extends PacketBase> void registerClientboundPacket(ResourceLocation id, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler)
public static <T extends PacketBase> void registerClientboundPacket(CustomPacketPayload.Type<T> id, BiConsumer<T, Player> handler)
{
ClientPlayNetworking.registerGlobalReceiver(id, (client, packetHandler, buf, responseSender) -> {
T packet = reader.apply(buf);
client.execute(() -> {
handler.accept(packet, client.player);
ClientPlayNetworking.registerGlobalReceiver(id, (T packet, ClientPlayNetworking.Context context) -> {
context.client().execute(() -> {
handler.accept(packet, context.player());
});
});
}

View File

@ -1,13 +1,56 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.attachment.v1.AttachmentRegistry;
import net.fabricmc.fabric.api.attachment.v1.AttachmentType;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerPlayer;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.config.fabric.ConfigLoaderImpl;
import tschipp.carryon.events.CommonEvents;
import java.io.IOException;
public class CarryOnFabricMod implements ModInitializer {
public static final AttachmentType<CarryOnData> CARRY_ON_DATA_ATTACHMENT_TYPE = AttachmentRegistry.create(
Identifier.fromNamespaceAndPath(Constants.MOD_ID, "carry_on_data"),
builder -> builder
.initializer(() -> new CarryOnData(new CompoundTag()))
.persistent(CarryOnData.CODEC)
.syncWith(CarryOnData.STREAM_CODEC, (t, p) ->{
ServerPlayer player = (ServerPlayer) t;
// the isAlive check avoids us syncing attachment data about dead players. Which causes a disconnect
// player.tickCount > 0 avoids us syncing attachment data about players the instant they spawn.
// Which also causes a disconnect as the player entity may not be synced yet.
return p.connection != null && player.isAlive() && !p.isRemoved() && player.tickCount > 0;
})
);
@Override
public void onInitialize() {
@ -25,6 +68,7 @@ public class CarryOnFabricMod implements ModInitializer {
CommonEvents.registerEvents();
CarryOnCommon.registerServerPackets();
CarryOnCommon.registerClientPackets(false);
}
}

View File

@ -0,0 +1,86 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.compat;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import tschipp.carryon.Constants;
import tschipp.carryon.platform.Services;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ArchitecturyCompat {
private static Object INVOKER_INSTANCE;
private static Method PLACE_BLOCK;
private static Method IS_FALSE;
@SuppressWarnings("unchecked")
private static void setup( ) {
try {
Class BlockEvent = Class.forName("dev.architectury.event.events.common.BlockEvent");
Field PLACE = BlockEvent.getField("PLACE");
Method invoker = Class.forName("dev.architectury.event.Event").getMethod("invoker");
INVOKER_INSTANCE = invoker.invoke(PLACE.get(BlockEvent));
Class PlaceClass = Class.forName("dev.architectury.event.events.common.BlockEvent$Place");
PLACE_BLOCK = PlaceClass.getMethod("placeBlock", Level.class, BlockPos.class, BlockState.class, Entity.class);
Class EventResult = Class.forName("dev.architectury.event.EventResult");
IS_FALSE = EventResult.getMethod("isFalse");
} catch (Exception e) {
Constants.LOG.warn("Error while initializing Architectury Compat: " + e);
}
}
public static boolean active() {
return Services.PLATFORM.isModLoaded("architectury");
}
public static boolean sendPlaceEvent(Level level, BlockPos pos, BlockState state, Player player) {
if(!active())
return true;
if(INVOKER_INSTANCE == null || PLACE_BLOCK == null)
setup();
if(INVOKER_INSTANCE != null && PLACE_BLOCK != null && IS_FALSE != null) {
try {
Object eventResult = PLACE_BLOCK.invoke(INVOKER_INSTANCE, level, pos, state, player);
boolean canceled = (boolean) IS_FALSE.invoke(eventResult);
return !canceled;
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return true;
}
}

View File

@ -0,0 +1,16 @@
package tschipp.carryon.compat;
import net.minecraft.client.gui.screens.Screen;
import tschipp.carryon.config.BuiltConfig;
import tschipp.carryon.config.fabric.ConfigLoaderImpl;
public class ClothConfigCompatFabric {
public static Screen createScreen(BuiltConfig client, BuiltConfig common, Screen screen) {
return ClothConfigCompat.getConfigScreen(client, common, screen, ConfigLoaderImpl::saveConfigs);
}
}

View File

@ -0,0 +1,17 @@
package tschipp.carryon.compat;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import tschipp.carryon.config.BuiltConfig;
import tschipp.carryon.config.fabric.ConfigLoaderImpl;
public class ModMenuCompat implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
BuiltConfig[] configs = ConfigLoaderImpl.CONFIGS.values().toArray(new BuiltConfig[0]);
return (parent) -> ClothConfigCompatFabric.createScreen(configs[1], configs[0], parent);
}
}

View File

@ -1,8 +1,29 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.config.fabric;
import com.google.gson.*;
import net.fabricmc.loader.api.FabricLoader;
import org.apache.commons.io.FileUtils;
import tschipp.carryon.common.config.ListHandler;
import tschipp.carryon.config.*;
import java.io.File;
@ -10,7 +31,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -19,7 +40,7 @@ public class ConfigLoaderImpl {
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
//Default JSON and config data.
public static final Map<JsonObject, BuiltConfig> CONFIGS = new HashMap<>();
public static final Map<JsonObject, BuiltConfig> CONFIGS = new LinkedHashMap<>();
public static void initialize() throws IOException {
Path cfgPath = FabricLoader.getInstance().getConfigDir();
@ -31,6 +52,11 @@ public class ConfigLoaderImpl {
FileUtils.write(cfgFile, GSON.toJson(entry.getKey()), StandardCharsets.UTF_8);
} else {
JsonObject cfgJson = GSON.fromJson(FileUtils.readFileToString(cfgFile, StandardCharsets.UTF_8), JsonObject.class);
if(cfgJson == null)
{
cfgPath.toFile().mkdirs();
FileUtils.write(cfgFile, GSON.toJson(entry.getKey()), StandardCharsets.UTF_8);
}
FileUtils.write(cfgFile, GSON.toJson(loadConfig(entry.getValue(), cfgJson)), StandardCharsets.UTF_8);
}
}
@ -43,11 +69,11 @@ public class ConfigLoaderImpl {
JsonElement value = entry.getValue();
if (value instanceof JsonPrimitive configValue) {
category.getProperty(id).ifPresent(data -> {
if (configValue.isBoolean() && data.data().type().equals(PropertyType.BOOLEAN))
if (configValue.isBoolean() && data.getData().type().equals(PropertyType.BOOLEAN))
data.setBoolean(configValue.getAsBoolean());
if (configValue.isNumber() && data.data().type().equals(PropertyType.INT)) {
if (configValue.isNumber() && data.getData().type().equals(PropertyType.INT)) {
int configInt = configValue.getAsInt();
if (configInt > data.data().max() || configInt < data.data().min()) {
if (configInt > data.getData().max() || configInt < data.getData().min()) {
try {
config.addProperty(id, data.getInt());
} catch (IllegalAccessException ignored) {
@ -56,9 +82,9 @@ public class ConfigLoaderImpl {
data.setInt(configInt);
}
}
if (configValue.isNumber() && data.data().type().equals(PropertyType.DOUBLE)) {
if (configValue.isNumber() && data.getData().type().equals(PropertyType.DOUBLE)) {
double configDouble = configValue.getAsDouble();
if (configDouble > data.data().maxD() || configDouble < data.data().minD()) {
if (configDouble > data.getData().maxD() || configDouble < data.getData().minD()) {
try {
config.addProperty(id, data.getDouble());
} catch (IllegalAccessException ignored) {
@ -72,7 +98,7 @@ public class ConfigLoaderImpl {
category.getCategory(id).ifPresent(cat -> loadConfig(cat, subConfig));
} else if (value instanceof JsonArray list) {
category.getProperty(id).ifPresent(data -> {
if(data.data().type() == PropertyType.STRING_ARRAY)
if(data.getData().type() == PropertyType.STRING_ARRAY)
{
List<String> ls = new ArrayList<>();
for(JsonElement arrEle : list)
@ -91,6 +117,20 @@ public class ConfigLoaderImpl {
return config;
}
public static void saveConfigs() {
try {
Path cfgPath = FabricLoader.getInstance().getConfigDir();
for (Map.Entry<JsonObject, BuiltConfig> entry : CONFIGS.entrySet()) {
File cfgFile = new File(cfgPath.toFile(), entry.getValue().fileName+".json");
cfgPath.toFile().mkdirs();
FileUtils.write(cfgFile, GSON.toJson(entry.getKey()), StandardCharsets.UTF_8);
}
ListHandler.initConfigLists();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void registerConfig(BuiltConfig config) {
try {
JsonObject configJson = new JsonObject();
@ -110,21 +150,39 @@ public class ConfigLoaderImpl {
builder.add(category.category, categoryJson);
}
@SuppressWarnings("unchecked")
private static void buildProperty(JsonObject builder, PropertyData data) throws IllegalAccessException {
AnnotationData annotationData = data.data();
AnnotationData annotationData = data.getData();
builder.addProperty("//"+data.getId(), annotationData.description());
switch (annotationData.type()) {
case BOOLEAN -> builder.addProperty(data.getId(), data.getBoolean());
case INT -> builder.addProperty(data.getId(), data.getInt());
case DOUBLE -> builder.addProperty(data.getId(), data.getDouble());
case STRING_ARRAY -> {
case BOOLEAN:
builder.addProperty(data.getId(), data.getBoolean());
data.setSetter((b) -> {builder.addProperty(data.getId(), (boolean)b); data.setBoolean((boolean)b);});
break;
case INT:
builder.addProperty(data.getId(), data.getInt());
data.setSetter((b) -> {builder.addProperty(data.getId(), (int)b); data.setInt((int)b);});
break;
case DOUBLE:
builder.addProperty(data.getId(), data.getDouble());
data.setSetter((b) -> {builder.addProperty(data.getId(), (double)b); data.setDouble((double)b);});
break;
case STRING_ARRAY:
JsonArray arr = new JsonArray();
for(String s : data.getStringArray())
arr.add(s);
builder.add(data.getId(), arr);
}
default -> throw new IllegalAccessException("Unknown property type.");
data.setSetter(list -> {
JsonArray overwrite = new JsonArray();
for(String s : (List<String>)list)
overwrite.add(s);
builder.add(data.getId(), overwrite);
data.setStringArray(((List<?>) list).toArray(new String[0]));
});
break;
default:
throw new IllegalAccessException("Unknown property type.");
}
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.events;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;

View File

@ -1,11 +1,33 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.events;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.CommonLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.player.*;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@ -19,6 +41,7 @@ import tschipp.carryon.common.carry.CarryOnDataManager;
import tschipp.carryon.common.carry.PickupHandler;
import tschipp.carryon.common.carry.PlacementHandler;
import tschipp.carryon.common.scripting.ScriptReloadListener;
import tschipp.carryon.compat.ArchitecturyCompat;
import tschipp.carryon.config.ConfigLoader;
import tschipp.carryon.scripting.IdentifiableScriptReloadListener;
@ -28,12 +51,12 @@ public class CommonEvents {
CommonLifecycleEvents.TAGS_LOADED.register((registries, client) -> {
if(!client)
ConfigLoader.onConfigLoaded();
ConfigLoader.onConfigLoaded(registries);
});
UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> {
if(world.isClientSide)
if(world.isClientSide())
return InteractionResult.PASS;
BlockPos pos = hitResult.getBlockPos();
@ -42,7 +65,10 @@ public class CommonEvents {
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if(!carry.isCarrying())
{
if (PickupHandler.tryPickUpBlock((ServerPlayer) player, pos, world, null))
if (PickupHandler.tryPickUpBlock((ServerPlayer) player, pos, world, (pState, pPos) -> {
boolean success = PlayerBlockBreakEvents.BEFORE.invoker().beforeBlockBreak(world, player, pPos, pState, world.getBlockEntity(pPos));
return success;
}))
return InteractionResult.SUCCESS;
return InteractionResult.PASS;
}
@ -50,7 +76,9 @@ public class CommonEvents {
{
if(carry.isCarrying(CarryOnData.CarryType.BLOCK))
{
if(PlacementHandler.tryPlaceBlock((ServerPlayer) player, pos, facing, null))
if(PlacementHandler.tryPlaceBlock((ServerPlayer) player, pos, facing, (pState, pPos) -> {
return ArchitecturyCompat.sendPlaceEvent(world, pState, pPos, player);
}))
return InteractionResult.SUCCESS;
}
else
@ -69,7 +97,7 @@ public class CommonEvents {
UseEntityCallback.EVENT.register((player, level, hand, entity, hitResult) -> {
if(level.isClientSide)
if(level.isClientSide())
return InteractionResult.PASS;
CarryOnData carry = CarryOnDataManager.getCarryData(player);
@ -105,12 +133,10 @@ public class CommonEvents {
CarryOnCommon.onCarryTick(player);
});
ServerPlayerEvents.COPY_FROM.register(((oldPlayer, newPlayer, alive) -> {
PlacementHandler.placeCarriedOnDeath(oldPlayer, newPlayer, !alive);
}));
PlayerBlockBreakEvents.BEFORE.register(((world, player, pos, state, blockEntity) -> {
if(!CarryOnCommon.onTryBreakBlock(player))
return false;
@ -129,7 +155,23 @@ public class CommonEvents {
return InteractionResult.PASS;
}));
//TODO: drop carried when attacked
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
CarryOnCommon.onRiderDisconnected(handler.getPlayer());
});
ServerLivingEntityEvents.ALLOW_DEATH.register((entity, damageSource, damageAmount) -> {
if(entity instanceof ServerPlayer sp) {
CarryOnCommon.onRiderDisconnected(sp);
}
return true;
});
ServerLivingEntityEvents.ALLOW_DAMAGE.register((entity, source, amount) -> {
if(entity instanceof ServerPlayer sp) {
CarryOnCommon.onPlayerAttacked(sp);
}
return true;
});
}
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;

View File

@ -1,31 +1,44 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderBuffers;
import net.minecraft.client.renderer.SubmitNodeCollector;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import tschipp.carryon.client.render.CarriedObjectRender;
import tschipp.carryon.client.render.CarryRenderHelper;
import tschipp.carryon.platform.Services;
@Mixin(ItemInHandRenderer.class)
public class ItemInHandRendererMixin
{
@Inject(at = @At(value = "HEAD"), method = "renderArmWithItem(Lnet/minecraft/client/player/AbstractClientPlayer;FFLnet/minecraft/world/InteractionHand;FLnet/minecraft/world/item/ItemStack;FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", cancellable = true)
private void onRenderHand(AbstractClientPlayer player, float partialTicks, float pitch, InteractionHand hand, float pSwingProgress, ItemStack pStack, float pEquippedProgress, PoseStack poseStack, MultiBufferSource buffer, int light, CallbackInfo ci)
@Inject(at = @At(value = "HEAD"), method = "renderArmWithItem(Lnet/minecraft/client/player/AbstractClientPlayer;FFLnet/minecraft/world/InteractionHand;FLnet/minecraft/world/item/ItemStack;FLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;I)V", cancellable = true)
private void renderArmWithItem(AbstractClientPlayer player, float partialTick, float pitch, InteractionHand hand, float swingProgress, ItemStack item, float equippedProgress, PoseStack poseStack, SubmitNodeCollector nodeCollector, int packedLight, CallbackInfo ci)
{
if(CarryRenderHelper.getPerspective() == 0 && CarriedObjectRender.drawFirstPerson(player, buffer, poseStack, light, partialTicks))
if(CarriedObjectRender.draw(player, poseStack, packedLight, partialTick,nodeCollector,true))
ci.cancel();
}

View File

@ -1,23 +0,0 @@
package tschipp.carryon.mixin;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LightTexture;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import tschipp.carryon.client.render.CarriedObjectRender;
@Mixin(LevelRenderer.class)
public class LevelRendererMixin
{
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;F)V"), method = "renderLevel(Lcom/mojang/blaze3d/vertex/PoseStack;FJZLnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/GameRenderer;Lnet/minecraft/client/renderer/LightTexture;Lcom/mojang/math/Matrix4f;)V")
private void onRenderLevel(PoseStack poseStack, float f, long l, boolean bl, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f matrix4f, CallbackInfo ci)
{
CarriedObjectRender.drawThirdPerson(gameRenderer.getMinecraft().getFrameTime(), poseStack);
}
}

View File

@ -1,5 +1,26 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.player.Player;
@ -15,13 +36,13 @@ import tschipp.carryon.common.carry.PlacementHandler;
@Mixin(Player.class)
public class PlayerMixinFabric
{
@Inject(at = @At("HEAD"), method = "hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")
private void onHurt(DamageSource damageSource, float f, CallbackInfoReturnable<Boolean> cir) {
@Inject(at = @At("HEAD"), method = "hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z")
private void onHurt(ServerLevel level, DamageSource damageSource, float amount, CallbackInfoReturnable<Boolean> cir) {
if(Constants.COMMON_CONFIG.settings.dropCarriedWhenHit)
{
Player player = ((Player)(Object)this);
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if(carry.isCarrying() && !player.level.isClientSide)
if(carry.isCarrying())
PlacementHandler.placeCarried((ServerPlayer)player);
}

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.mixin;
import net.minecraft.client.Minecraft;
@ -14,9 +34,10 @@ import tschipp.carryon.common.carry.CarryOnDataManager;
@Mixin(Screen.class)
public class ScreenMixin
{
@Inject(at = @At(value = "TAIL"), method = "init(Lnet/minecraft/client/Minecraft;II)V")
private void onInit(Minecraft mc, int i, int j, CallbackInfo ci)
@Inject(at = @At(value = "TAIL"), method = "init(II)V")
private void onInit(int width, int height, CallbackInfo ci)
{
Minecraft mc = Minecraft.getInstance();
Player player = mc.player;
if((Object)this instanceof AbstractContainerScreen && player != null)
{

View File

@ -1,3 +1,23 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.platform;
import net.minecraft.world.entity.player.Player;

View File

@ -1,20 +1,44 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.platform;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.Identifier;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.CarryOnFabricClientMod;
import tschipp.carryon.CarryOnFabricMod;
import tschipp.carryon.common.carry.CarryOnData;
import tschipp.carryon.config.BuiltConfig;
import tschipp.carryon.config.fabric.ConfigLoaderImpl;
import tschipp.carryon.networking.PacketBase;
import tschipp.carryon.platform.services.IPlatformHelper;
import java.util.function.BiConsumer;
import java.util.function.Function;
public class FabricPlatformHelper implements IPlatformHelper {
@ -40,34 +64,51 @@ public class FabricPlatformHelper implements IPlatformHelper {
ConfigLoaderImpl.registerConfig(cfg);
}
@SuppressWarnings("unchecked")
@Override
public <T extends PacketBase> void registerServerboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler)
public <T extends PacketBase, B extends FriendlyByteBuf> void registerServerboundPacket(CustomPacketPayload.Type<T> type, Class<T> clazz, StreamCodec<B, T> codec, BiConsumer<T, Player> handler, Object... args)
{
ServerPlayNetworking.registerGlobalReceiver(id, (server, player, packetHandler, buf, responseSender) -> {
T packet = reader.apply(buf);
server.execute(() -> {
handler.accept(packet, player);
PayloadTypeRegistry.playC2S().register(type, (StreamCodec<RegistryFriendlyByteBuf, T>)codec);
ServerPlayNetworking.registerGlobalReceiver(type, (T packet, ServerPlayNetworking.Context context) -> {
context.server().execute(() -> {
handler.accept(packet, context.player());
});
});
}
@SuppressWarnings("unchecked")
@Override
public <T extends PacketBase> void registerClientboundPacket(ResourceLocation id, int numericalId, Class<T> clazz, BiConsumer<T, FriendlyByteBuf> writer, Function<FriendlyByteBuf, T> reader, BiConsumer<T, Player> handler)
public <T extends PacketBase, B extends FriendlyByteBuf> void registerClientboundPacket(CustomPacketPayload.Type<T> type, Class<T> clazz, StreamCodec<B, T> codec, BiConsumer<T, Player> handler, Object... args)
{
CarryOnFabricClientMod.registerClientboundPacket(id, reader, handler);
boolean client = (boolean)args[0];
if(!client)
PayloadTypeRegistry.playS2C().register(type, (StreamCodec<RegistryFriendlyByteBuf, T>)codec);
else
CarryOnFabricClientMod.registerClientboundPacket(type, handler);
}
@Override
public void sendPacketToServer(ResourceLocation id, PacketBase packet)
public void sendPacketToServer(Identifier id, PacketBase packet)
{
CarryOnFabricClientMod.sendPacketToServer(id, packet);
CarryOnFabricClientMod.sendPacketToServer(packet);
}
@Override
public void sendPacketToPlayer(ResourceLocation id, PacketBase packet, ServerPlayer player)
public void sendPacketToPlayer(Identifier id, PacketBase packet, ServerPlayer player)
{
FriendlyByteBuf buf = PacketByteBufs.create();
packet.toBytes(buf);
ServerPlayNetworking.send(player, id, buf);
ServerPlayNetworking.send(player, packet);
}
@Override
public CarryOnData getCarryData(Player player) {
CarryOnData data = player.getAttachedOrCreate(CarryOnFabricMod.CARRY_ON_DATA_ATTACHMENT_TYPE);
return data.clone();
}
@Override
public void setCarryData(Player player, CarryOnData data) {
player.setAttached(CarryOnFabricMod.CARRY_ON_DATA_ATTACHMENT_TYPE, data);
}
}

View File

@ -1,15 +1,35 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.scripting;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import tschipp.carryon.Constants;
import tschipp.carryon.common.scripting.ScriptReloadListener;
public class IdentifiableScriptReloadListener extends ScriptReloadListener implements IdentifiableResourceReloadListener
{
@Override
public ResourceLocation getFabricId()
public Identifier getFabricId()
{
return new ResourceLocation(Constants.MOD_ID, "carryon_scripts");
return Identifier.fromNamespaceAndPath(Constants.MOD_ID, "carryon_scripts");
}
}

View File

@ -2,14 +2,13 @@
"required": true,
"minVersion": "0.8",
"package": "tschipp.carryon.mixin",
"compatibilityLevel": "JAVA_17",
"compatibilityLevel": "JAVA_21",
"mixins": [
"PlayerMixinFabric"
],
"client": [
"ItemInHandRendererMixin",
"LevelRendererMixin",
"ScreenMixin"
"ScreenMixin"
],
"injectors": {
"defaultRequire": 1

View File

@ -1,11 +1,11 @@
{
"schemaVersion": 1,
"id": "carryon",
"id": "${mod_id}",
"version": "${version}",
"name": "Carry On",
"description": "Carry On is a simple mod that improves game interaction by allowing players to pick up, carry, and place single block Tile Entities using only their empty hands.",
"name": "${mod_name}",
"description": "${description}",
"authors": [
"Tschipp", "Purplicious_Cow", "cy4n"
"Tschipp", "Purplicious_Cow"
],
"contact": {
"homepage": "https://tschipp.ch/",
@ -13,7 +13,7 @@
"issues": "https://github.com/Tschipp/CarryOn/issues"
},
"license": "GNU LGPLv3",
"license": "${license}",
"icon": "logo.png",
"environment": "*",
@ -23,6 +23,9 @@
],
"client": [
"tschipp.carryon.CarryOnFabricClientMod"
],
"modmenu" : [
"tschipp.carryon.compat.ModMenuCompat"
]
},
"mixins": [
@ -31,10 +34,10 @@
],
"depends": {
"fabricloader": ">=0.14",
"fabric": "*",
"minecraft": "1.19.x",
"java": ">=17"
"fabricloader": ">=${fabric_loader_version}",
"fabric-api": "*",
"minecraft": "${minecraft_version_range_fabric}",
"java": ">=${java_version}"
}
}

View File

@ -1,36 +1,13 @@
buildscript {
repositories {
maven { url = 'https://maven.minecraftforge.net' }
maven { url = 'https://repo.spongepowered.org/repository/maven-public/' }
maven { url = 'https://maven.parchmentmc.org' }
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT'
classpath 'org.parchmentmc:librarian:1.+'
classpath 'gradle.plugin.com.github.johnrengelman:shadow:7.1.2'
}
}
apply plugin: 'java'
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'eclipse'
apply plugin: 'org.spongepowered.mixin'
apply plugin: 'maven-publish'
apply plugin: 'org.parchmentmc.librarian.forgegradle'
apply plugin: 'com.github.johnrengelman.shadow'
apply from: 'https://raw.githubusercontent.com/MinecraftModDevelopment/Gradle-Collection/22e7d543a18cd30675277fbfa3669e3d9e206010/generic/secrets.gradle'
if (project.hasProperty('secretFile')) {
loadSecrets(new File((String) findProperty('secretFile')))
}
if (System.getenv('BUILD_NUMBER') != null) {
version += "." + System.getenv('BUILD_NUMBER')
plugins {
id 'multiloader-loader'
id 'net.minecraftforge.gradle' version '[6.0.46,6.2)'
id 'org.spongepowered.mixin' version '0.7-SNAPSHOT'
id 'org.parchmentmc.librarian.forgegradle' version '1.+'
}
archivesBaseName = "${mod_id}-forge-${minecraft_version}"
base {
archivesName = "${mod_id}-forge-${minecraft_version}"
}
mixin {
add sourceSets.main, "${mod_id}.refmap.json"
@ -39,14 +16,25 @@ mixin {
config "${mod_id}.forge.mixins.json"
}
tasks.named('jar', Jar).configure {
manifest {
attributes([
"MixinConfigs" : "${mod_id}.mixins.json,${mod_id}.forge.mixins.json"
])
}
}
jarJar.enable()
build.dependsOn tasks.jarJar
minecraft {
mappings channel: 'parchment', version: "${parchment_mappings}"
if (project.hasProperty('forge_ats_enabled') && project.findProperty('forge_ats_enabled').toBoolean()) {
// This location is hardcoded in Forge and can not be changed.
// https://github.com/MinecraftForge/MinecraftForge/blob/be1698bb1554f9c8fa2f58e32b9ab70bc4385e60/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java#L123
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
project.logger.debug('Forge Access Transformers are enabled for this project.')
mappings channel: 'parchment', version: parchment_mappings
copyIdeResources = true
reobf = false
def at = file('src/main/resources/META-INF/accesstransformer.cfg')
if (at.exists()) {
accessTransformer = at
}
runs {
@ -56,6 +44,7 @@ minecraft {
taskName 'Client'
property 'mixin.env.remapRefMap', 'true'
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
property 'eventbus.api.strictRuntimeChecks', 'true'
args "-mixin.config=${mod_id}.mixins.json", "-mixin.config=${mod_id}.forge.mixins.json"
mods {
modClientRun {
@ -71,6 +60,7 @@ minecraft {
taskName 'Server'
property 'mixin.env.remapRefMap', 'true'
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
property 'eventbus.api.strictRuntimeChecks', 'true'
args "-mixin.config=${mod_id}.mixins.json", "-mixin.config=${mod_id}.forge.mixins.json"
mods {
modServerRun {
@ -87,6 +77,7 @@ minecraft {
taskName 'Data'
property 'mixin.env.remapRefMap', 'true'
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
property 'eventbus.api.strictRuntimeChecks', 'true'
args "-mixin.config=${mod_id}.mixins.json", "-mixin.config=${mod_id}.forge.mixins.json"
mods {
modDataRun {
@ -100,81 +91,61 @@ minecraft {
sourceSets.main.resources.srcDir 'src/generated/resources'
configurations {
shade
implementation.extendsFrom shade
}
repositories {
maven {
url 'https://maven.blamejared.com'
name = "Shedaniel"
url "https://maven.shedaniel.me/"
}
maven { url 'https://jitpack.io' }
flatDir {
dirs 'libs'
}
maven { url 'https://jitpack.io' }
}
dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
compileOnly project(":Common")
implementation fg.deobf("net.darkhax.gamestages:GameStages-Forge-1.19.2:11.0.2")
implementation fg.deobf("net.darkhax.bookshelf:Bookshelf-Forge-1.19.2:16.1.9")
minecraftLibrary(annotationProcessor(shade(("com.github.LlamaLad7:MixinExtras:${mixinextras_version}"))))
annotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor'
annotationProcessor 'org.spongepowered:mixin:0.8.5-SNAPSHOT:processor'
annotationProcessor 'net.minecraftforge:eventbus-validator:7.0-beta.7'
// Hack fix for now, force jopt-simple to be exactly 5.0.4 because Mojang ships that version, but some transitive dependencies request 6.0+
implementation('net.sf.jopt-simple:jopt-simple:5.0.4') { version { strictly '5.0.4' } }
testCompileOnly(compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:${mixinextras_version}")))
implementation(jarJar("io.github.llamalad7:mixinextras-forge:${mixinextras_version}")) {
jarJar.ranged(it, "[${mixinextras_version},)")
}
//implementation fg.deobf("net.darkhax.gamestages:GameStages-Forge-1.19.2:11.0.2")
compileOnly(fg.deobf("me.shedaniel.cloth:cloth-config-neoforge:${cloth_config_version}"))
fileTree("libs").matching {
include "*.jar"
include "*.jar"
}.each {
String filename = it.getName();
filename = filename.substring(0, filename.length() - 4);
int lastDash = filename.lastIndexOf("-");
filename = filename.substring(0, lastDash) + ":" + filename.substring(lastDash+1, filename.length());
implementation fg.deobf("blank:${filename}")
String filename = it.getName();
filename = filename.substring(0, filename.length() - 4);
int lastDash = filename.lastIndexOf("-");
filename = filename.substring(0, lastDash) + ":" + filename.substring(lastDash+1, filename.length());
implementation fg.deobf("blank:${filename}")
}
}
shadowJar {
configurations = [project.configurations.shade]
relocate 'com.llamalad7.mixinextras', 'tschipp.carryon.shaded.mixinextras'
finalizedBy 'reobfShadowJar'
archiveClassifier = ""
}
assemble.dependsOn shadowJar
reobf {
shadowJar {}
}
tasks.withType(JavaCompile) {
source(project(":Common").sourceSets.main.allSource)
}
processResources {
from project(":Common").sourceSets.main.resources
filesMatching('*.mixins.json') {
expand "refmap_target": "${mod_id}."
}
}
jar.finalizedBy('reobfJar')
publishing {
publications {
mavenJava(MavenPublication) {
groupId project.group
artifactId project.archivesBaseName
version project.version
artifact jar
}
}
repositories {
maven {
url "file://" + System.getenv("local_maven")
fg.component(it)
}
}
}
sourceSets.each {
def dir = layout.buildDirectory.dir("sourcesSets/$it.name")
it.output.resourcesDir = dir
it.java.destinationDirectory = dir
}

View File

@ -1,13 +1,36 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.resources.Identifier;
import net.minecraftforge.eventbus.api.listener.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;
import net.minecraftforge.network.ChannelBuilder;
import net.minecraftforge.network.SimpleChannel;
import tschipp.carryon.config.forge.ConfigLoaderImpl;
import tschipp.carryon.networking.ClientboundSyncCarryDataPacket;
import tschipp.carryon.platform.Services;
@Mod(Constants.MOD_ID)
@EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
@ -15,26 +38,31 @@ public class CarryOnForge {
public static SimpleChannel network;
public CarryOnForge() {
public CarryOnForge(FMLJavaModLoadingContext context) {
// This method is invoked by the Forge mod loader when it is ready
// to load your mod. You can access Forge and Common code in this
// project.
// Use Forge to bootstrap the Common mod.
CarryOnCommon.registerConfig();
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
ConfigLoaderImpl.initialize();
ConfigLoaderImpl.initialize(context);
}
private void setup(final FMLCommonSetupEvent event)
@SubscribeEvent
public static void setup(final FMLCommonSetupEvent event)
{
network = NetworkRegistry.newSimpleChannel(new ResourceLocation(Constants.MOD_ID, "carryonpackets"), () -> "1.0", "1.0"::equals, "1.0"::equals);
network = ChannelBuilder.named(Identifier.fromNamespaceAndPath(Constants.MOD_ID, "carryonpackets")).simpleChannel();
CarryOnCommon.registerServerPackets();
CarryOnCommon.registerClientPackets();
Services.PLATFORM.registerClientboundPacket(
ClientboundSyncCarryDataPacket.TYPE,
ClientboundSyncCarryDataPacket.class,
ClientboundSyncCarryDataPacket.CODEC,
ClientboundSyncCarryDataPacket::handle
);
}
}

View File

@ -0,0 +1,23 @@
package tschipp.carryon.carry;
import net.minecraft.nbt.CompoundTag;
import tschipp.carryon.common.carry.CarryOnData;
public class CarryOnDataCapability implements ICarryOnDataCapability {
private CarryOnData data;
public CarryOnDataCapability() {
this.data = new CarryOnData(new CompoundTag());
}
@Override
public CarryOnData getCarryData() {
return data;
}
@Override
public void setCarryData(CarryOnData data) {
this.data = data;
}
}

View File

@ -0,0 +1,38 @@
package tschipp.carryon.carry;
import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.CapabilityToken;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import tschipp.carryon.common.carry.CarryOnData;
public class CarryOnDataCapabilityProvider implements ICapabilitySerializable<CompoundTag> {
public static final Capability<ICarryOnDataCapability> CARRY_ON_DATA_CAPABILITY = CapabilityManager.get(new CapabilityToken<ICarryOnDataCapability>() {});
private final CarryOnDataCapability impl = new CarryOnDataCapability();
private final LazyOptional<ICarryOnDataCapability> opt = LazyOptional.of(() -> impl);
@Override
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
return cap == CARRY_ON_DATA_CAPABILITY ? opt.cast() : LazyOptional.empty();
}
@Override
public CompoundTag serializeNBT(HolderLookup.Provider registryAccess) {
return (CompoundTag) CarryOnData.CODEC.encodeStart(NbtOps.INSTANCE, impl.getCarryData()).getOrThrow();
}
@Override
public void deserializeNBT(HolderLookup.Provider registryAccess, CompoundTag nbt) {
CarryOnData data = CarryOnData.CODEC.parse(NbtOps.INSTANCE, nbt).getOrThrow();
impl.setCarryData(data);
}
}

View File

@ -0,0 +1,13 @@
package tschipp.carryon.carry;
import net.minecraftforge.common.capabilities.AutoRegisterCapability;
import tschipp.carryon.common.carry.CarryOnData;
@AutoRegisterCapability
public interface ICarryOnDataCapability {
CarryOnData getCarryData();
void setCarryData(CarryOnData data);
}

View File

@ -1,12 +1,54 @@
/*
* GNU Lesser General Public License v3
* Copyright (C) 2024 Tschipp
* mrtschipp@gmail.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package tschipp.carryon.compat;
import net.darkhax.gamestages.GameStageHelper;
import net.minecraft.world.entity.player.Player;
import tschipp.carryon.Constants;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class GamestageCompat
{
private static Method hasStage;
static {
try {
Class<?> gamestageHelper = Class.forName("net.darkhax.gamestages.GameStageHelper");
hasStage = gamestageHelper.getMethod("hasStage", Player.class, String.class);
} catch (Exception e) {
Constants.LOG.info("Gamestages not found. Disabling.");
}
}
public static boolean hasStage(Player player, String stage)
{
return GameStageHelper.hasStage(player, stage);
if(hasStage == null)
return true;
try {
return (boolean) hasStage.invoke(null, player, stage);
} catch (IllegalAccessException | InvocationTargetException e) {
}
return true;
}
}

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