更新版本为1.0.7
1. 修复 #5 #9 的问题: 服务器端崩溃(因为依赖加载了客户端专属类,感谢 璃之雨 和 AtinyFurina 的指正) 2.添加了Datagen 3.引入自写的库[Lib39](https://github.com/3944Realms/Lib39/tree/Forge_1_20_1)来辅助Datagen,理论上是不需要安装Lib39的 4.更新了Readme
This commit is contained in:
parent
bf5e9f98b9
commit
9511f0074c
51
README.md
51
README.md
|
|
@ -15,8 +15,8 @@ All you need is a cannon and enough gunpowder, and you can experience a journey
|
|||
| Mod Update Plan | Status |
|
||||
|----------------|--------|
|
||||
| Migration to Forge 1.20.1 | ✅ Completed |
|
||||
| Migration to higher versions of NeoForge | Not started, planned for July/August |
|
||||
| Open API for cross-mod compatibility | Not started, planned for July/August |
|
||||
| Migration to higher versions of NeoForge | Not started |
|
||||
| Open API for cross-mod compatibility | Not started, |
|
||||
| Improve and refactor the original mod's operations | Not started |
|
||||
|
||||
## Mod Development Statement
|
||||
|
|
@ -26,33 +26,30 @@ This mod is a migration and refactor of **Blast Travel** (the original mod only
|
|||
- The **1.20.1 Quilt version** is based on **Abbie5's fork**, with the MODID remaining as `blasttravel`.
|
||||
- The **1.20.1 Forge version** is a partial logic refactor by the author, with the MODID changed to `blasttravelreborn`. Please note the difference.
|
||||
|
||||
## Q&A
|
||||
|
||||
**Q1: Will there be Fabric support for future higher versions?**
|
||||
**A1:** Probably not. The author is not a fan of Fabric's development workflow. However, anyone is welcome to fork the project and develop a Fabric version. That said, the author might consider using the **Architectury** framework for multi-loader support (though it would be quite a hassle).
|
||||
|
||||
**Q2: Can my mod integrate with this mod?**
|
||||
**A2:** Yes! The author welcomes mod integrations. If you're a mod developer interested in compatibility, feel free to submit an **ISSUE** in this repository. The author is happy to provide code-level support.
|
||||
|
||||
**Q3: Will you support versions below 1.19.2?**
|
||||
**A3:** No. The author will **never** backport to lower versions. However, there is a mod with similar functionality—**Cannon (Teacon2022 Example Mod)**, which supports **1.18–1.18.2** and can serve as an alternative.
|
||||
|
||||
# Adding to Your Project
|
||||
1. Download mod jar file,and put it under your project's 'libs/' dir, and rename it into "{modid}-{minecraft-version}-{mod_version}.jar"(for example, "blasttravelreborn-1.20.1-1.0.6-forge-all.jar")
|
||||
2. Ensure your `build.gradle` has enable 'libs' flatDir repositories
|
||||
```groovy
|
||||
repositories {
|
||||
flatDir {
|
||||
dir 'libs'
|
||||
}
|
||||
# For Developer
|
||||
You can integrate and automatically download JsonEM for your mod project using Gradle.
|
||||
Just add the following to your build script (`build.gradle`):
|
||||
|
||||
## Repositories
|
||||
```gradle
|
||||
repositories {
|
||||
maven {
|
||||
name = "LTD Maven"
|
||||
url = "https://nexus.bot.leisuretimedock.top/repository/maven-public/"
|
||||
}
|
||||
````
|
||||
3. Add it to dependencies
|
||||
```groovy
|
||||
dependencies {
|
||||
implementation fg.deobf("blank:blasttravelreborn-1.20.1:1.0.6-forge-all")//for example
|
||||
}
|
||||
````
|
||||
}
|
||||
```
|
||||
### Forge
|
||||
```gradle
|
||||
dependencies {
|
||||
implementation fg.deobf("com.leisuretimedock.blastravelreborn:${minecraft_version}-${blasttravelreborn_version})"
|
||||
}
|
||||
```
|
||||
### Choose a Version
|
||||
|
||||
`${mc_version}` gets replaced by the current Minecraft version. (i.e. `1.20.1`)
|
||||
`${blasttravelreborn_version}` gets replaced by the version of JEI you want to use (i.e `1.0.7`)
|
||||
Cannon Model please install [BlockBench Plugin](https://github.com/LeisureTimeDock/JsonEM_Neo_Forge/blob/1.21/jsonem_models.js) in your BlockBench.
|
||||
|
||||
And import 'entity/cannon/main.json' with this jsonem plugin. Then you can view the cannon model correctly and create its texture.
|
||||
54
build.gradle
54
build.gradle
|
|
@ -8,6 +8,7 @@ buildscript {
|
|||
|
||||
plugins {
|
||||
id 'eclipse'
|
||||
id 'maven-publish'
|
||||
id 'idea'
|
||||
id 'net.minecraftforge.gradle' version '[6.0.16,6.2)'
|
||||
id 'org.parchmentmc.librarian.forgegradle' version '1.+'
|
||||
|
|
@ -152,7 +153,11 @@ repositories {
|
|||
}
|
||||
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so.
|
||||
// See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver
|
||||
flatDir {
|
||||
maven {
|
||||
name = "LTD Maven"
|
||||
url = "https://nexus.bot.leisuretimedock.top/repository/maven-public/"
|
||||
}
|
||||
flatDir {
|
||||
dir 'libs'
|
||||
}
|
||||
|
||||
|
|
@ -167,9 +172,12 @@ dependencies {
|
|||
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
|
||||
implementation 'org.spongepowered:mixin:0.8.5'
|
||||
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
|
||||
implementation jarJar(fg.deobf("blank:jsonem-${minecraft_version}:${jsonem_version}")) {
|
||||
jarJar.ranged(it, "[0.0,)")
|
||||
implementation "top.r3944realms.lib39:lib39:${lib39_version}"
|
||||
implementation jarJar(fg.deobf("com.leisuretimedock:jsonem-forge-${minecraft_version}:${jsonem_version}")) {
|
||||
jarJar.ranged(it, "[${jsonem_version},)")
|
||||
}
|
||||
|
||||
|
||||
// Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings
|
||||
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
|
||||
// compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}")
|
||||
|
|
@ -226,3 +234,43 @@ tasks.named('jar', Jar).configure {
|
|||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifactId = base.archivesName.get()
|
||||
from components.java
|
||||
artifactId = "${mod_id}-${project.name}-${minecraft_version}"
|
||||
|
||||
pom {
|
||||
name = rootProject.mod_id
|
||||
description = rootProject.mod_description
|
||||
url = rootProject.mod_source
|
||||
licenses {
|
||||
license {
|
||||
name = rootProject.mod_license
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = rootProject.mod_id
|
||||
name = rootProject.mod_authors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "file://${project.projectDir}/mcmodsrepo"
|
||||
}
|
||||
maven {
|
||||
name = 'LTDNexus'
|
||||
url = 'https://nexus.bot.leisuretimedock.top/repository/maven-releases/'
|
||||
credentials {
|
||||
username = System.getenv('LTDNexusUsername') ?: ''
|
||||
password = System.getenv('LTDNexusPassword') ?: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -38,8 +38,10 @@ mod_name=BlastTravel-Reborn
|
|||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||
mod_license=MIT
|
||||
# The mod version. See https://semver.org/
|
||||
mod_version=1.0.6+1.20.1-forge
|
||||
jsonem_version=0.2.2+1.20-fabrge
|
||||
mod_version=1.0.7
|
||||
jsonem_version=0.2.4
|
||||
lib39_version=1.20.1-0.0.17
|
||||
mod_source=https://github.com/LeisureTimeDock/BlastTravel_Neo_Forge
|
||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||
# This should match the base package used for the mod sources.
|
||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
|
|
@ -47,4 +49,4 @@ mod_group_id=com.leisuretimedock.blasttravelreborn
|
|||
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
|
||||
mod_authors=FoundationGames(Original Author), Abbie5(Migrate into Quilt 1.20.1), R3944Realms
|
||||
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
|
||||
mod_description=Migrate from Quilt 1.20.1,1.19.2
|
||||
mod_description=Migrate from Quilt 1.20.1, 1.19.2
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
787f3aedc203dff6fcef2b438729cc7e
|
||||
|
|
@ -0,0 +1 @@
|
|||
0446695fdc79163fa7a1ce6e792172fbcdbaafc1
|
||||
|
|
@ -0,0 +1 @@
|
|||
0195af1841c2087eb2a10cbc75e0b9fc1d30f62f2a752a6797acbb3d503b8af3
|
||||
|
|
@ -0,0 +1 @@
|
|||
ac8caf27e4c5d9e7d04fb6b4eff0bc5aa27e8e0440be346cbf2161c775a5a23c5326c201a83d93fbaea95ee40c8a6fb0a649b5db0d3cc0b14f11dfb8568c3c0f
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.leisuretimedock.blasttravelreborn</groupId>
|
||||
<artifactId>blasttravel-reborn</artifactId>
|
||||
<version>1.0.6+1.20.1-forge</version>
|
||||
</project>
|
||||
|
|
@ -0,0 +1 @@
|
|||
e3426fd0c4b900d1cad53c5308a75011
|
||||
|
|
@ -0,0 +1 @@
|
|||
8e2b7ac803f1a5d1bf02a9ef77fcf48d6f138cbb
|
||||
|
|
@ -0,0 +1 @@
|
|||
48136ed719d64d3e436b1782f494892fdb7abd6f08b9ff7750c07201bc9ff8f8
|
||||
|
|
@ -0,0 +1 @@
|
|||
30938abad6f11d4d26e73abe9cee3cb8321def9421f530574e68a89010f79e56e3bd860ec491e25a5a841a4787ea93a094675ecfc114b193137f808a558ab16c
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>com.leisuretimedock.blasttravelreborn</groupId>
|
||||
<artifactId>blasttravel-reborn</artifactId>
|
||||
<versioning>
|
||||
<latest>1.0.6+1.20.1-forge</latest>
|
||||
<release>1.0.6+1.20.1-forge</release>
|
||||
<versions>
|
||||
<version>1.0.6+1.20.1-forge</version>
|
||||
</versions>
|
||||
<lastUpdated>20250612155714</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
|
|
@ -0,0 +1 @@
|
|||
7be97661cf89db9c24d0e144216f7911
|
||||
|
|
@ -0,0 +1 @@
|
|||
bcbda3d6ce62aa2d5daa5cd991285b008b51ea81
|
||||
|
|
@ -0,0 +1 @@
|
|||
e56c09fc1d1fa062ea5b77ea5673c19c4a56ee4b91450646d2aed786832ce267
|
||||
|
|
@ -0,0 +1 @@
|
|||
3bdb8ae4325fd516bfaafeb33b0221f51f88eadd8388e3c49ea7f160eca95d34f5e04809a389afd6af913e21bf4985dd3a6d99cb4b491e12961b458293110f62
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
// 1.20.1 2025-11-22T19:25:06.9619789 Registries
|
||||
e615490187adee92d48183e84dd6953d340753c2 data/blasttravelreborn/damage_type/cannon.json
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
// 1.20.1 2025-11-22T19:25:06.9619789 Languages: zh_tw
|
||||
094e7efc852fc45d55f97c0976bf2453de88e219 assets/blasttravelreborn/lang/zh_tw.json
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
// 1.20.1 2025-11-22T19:25:06.9619789 Languages: zh_cn
|
||||
03cccc87a6370bef5c6b95b1d76cd9d22547b86c assets/blasttravelreborn/lang/zh_cn.json
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
// 1.20.1 2025-11-22T19:25:06.9619789 Item Models: blasttravelreborn
|
||||
3efedd95103ec88f295ab752f9591da6f20e9cb2 assets/blasttravelreborn/models/item/cannon.json
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// 1.20.1 2025-11-22T19:25:06.9619789 Recipes
|
||||
d38155e7a052e0f1143b0b82dc1a595026c4d98c data/blasttravelreborn/advancements/recipes/misc/cannon.json
|
||||
7fd4c6df73dc342481e69f6d24914ca8e767b578 data/blasttravelreborn/recipes/cannon.json
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
// 1.20.1 2025-11-22T19:28:42.6814983 Particle Descriptions
|
||||
1aacb18bd6bc829ecf1ac93ae1e3e4a9c30459b9 assets/blasttravelreborn/particles/cannon_blast.json
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
// 1.20.1 2025-11-22T19:25:06.9619789 Languages: en_us
|
||||
c3f0d412d3d39f47d1dd4065782d0984a17ed4e7 assets/blasttravelreborn/lang/en_us.json
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"container.blasttravelreborn.cannon_container_menu": "Cannon",
|
||||
"death.attack.blasttravelreborn.cannon": "%s was knocked out by a flying %s",
|
||||
"dialog.blasttravelreborn.full_cannon": "Cannon is full!",
|
||||
"dialog.blasttravelreborn.no_gunpowder": "Cannon has no gunpowder!",
|
||||
"entity.blasttravelreborn.cannon": "Cannon",
|
||||
"item.blasttravelreborn.cannon": "Cannon",
|
||||
"mount.blasttravelreborn.cannon.onboard": "Press %s to Exit, or %s to Fire"
|
||||
}
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
{
|
||||
"container.blasttravelreborn.cannon_container_menu": "大炮",
|
||||
"item.blasttravelreborn.cannon": "大炮",
|
||||
"entity.blasttravelreborn.cannon": "大炮实体",
|
||||
|
||||
"container.blasttravelreborn.cannon_container_menu": "大炮实体",
|
||||
"death.attack.blasttravelreborn.cannon": "%s被飞行的%s击倒了",
|
||||
"dialog.blasttravelreborn.full_cannon": "大炮已装满!",
|
||||
"dialog.blasttravelreborn.no_gunpowder": "大炮没有火药了!",
|
||||
"entity.blasttravelreborn.cannon": "大炮",
|
||||
"item.blasttravelreborn.cannon": "大炮",
|
||||
"mount.blasttravelreborn.cannon.onboard": "按%s离开,或按%s发射"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"container.blasttravelreborn.cannon_container_menu": "大砲實體",
|
||||
"death.attack.blasttravelreborn.cannon": "%s被飛行的%s擊倒了",
|
||||
"dialog.blasttravelreborn.full_cannon": "大砲已裝滿!",
|
||||
"dialog.blasttravelreborn.no_gunpowder": "大砲沒有火藥了!",
|
||||
"entity.blasttravelreborn.cannon": "大砲",
|
||||
"item.blasttravelreborn.cannon": "大砲",
|
||||
"mount.blasttravelreborn.cannon.onboard": "按%s離開,或按%s發射"
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "blasttravelreborn:item/cannon"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"textures": [
|
||||
"blasttravelreborn:blast_smoke_0",
|
||||
"blasttravelreborn:blast_smoke_1",
|
||||
"blasttravelreborn:blast_smoke_2",
|
||||
"blasttravelreborn:blast_smoke_3",
|
||||
"blasttravelreborn:blast_smoke_4",
|
||||
"blasttravelreborn:blast_smoke_5",
|
||||
"blasttravelreborn:blast_smoke_6",
|
||||
"blasttravelreborn:blast_smoke_7"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"criteria": {
|
||||
"has_iron_block": {
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": [
|
||||
"minecraft:iron_block"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"trigger": "minecraft:inventory_changed"
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"conditions": {
|
||||
"recipe": "blasttravelreborn:cannon"
|
||||
},
|
||||
"trigger": "minecraft:recipe_unlocked"
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_iron_block",
|
||||
"has_the_recipe"
|
||||
]
|
||||
],
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"blasttravelreborn:cannon"
|
||||
]
|
||||
},
|
||||
"sends_telemetry_event": false
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"exhaustion": 0.0,
|
||||
"message_id": "cannon",
|
||||
"exhaustion": 0,
|
||||
"scaling": "when_caused_by_living_non_player"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "misc",
|
||||
"key": {
|
||||
"A": {
|
||||
"item": "minecraft:iron_block"
|
||||
},
|
||||
"B": {
|
||||
"item": "minecraft:string"
|
||||
},
|
||||
"C": {
|
||||
"tag": "minecraft:stone_crafting_materials"
|
||||
},
|
||||
"D": {
|
||||
"item": "minecraft:stick"
|
||||
},
|
||||
"E": {
|
||||
"tag": "minecraft:logs"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
" A",
|
||||
"BA ",
|
||||
"CDE"
|
||||
],
|
||||
"result": {
|
||||
"item": "blasttravelreborn:cannon"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
|
@ -9,12 +9,10 @@ import net.minecraft.resources.ResourceLocation;
|
|||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Mod(value = BlastTravelReborn.MOD_ID)
|
||||
public class BlastTravelReborn {
|
||||
public static final String MOD_ID = "blasttravelreborn";
|
||||
public static final Logger LOG = LoggerFactory.getLogger("Blast Travel Reborn");
|
||||
public BlastTravelReborn() {
|
||||
FMLJavaModLoadingContext fmlJavaModLoadingContext = FMLJavaModLoadingContext.get();
|
||||
IEventBus modEventBus = fmlJavaModLoadingContext.getModEventBus();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package com.leisuretimedock.blasttravelreborn.api.events;
|
||||
|
||||
import com.leisuretimedock.blasttravelreborn.content.entity.cannon.CannonBehavior;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class RegisterCannonBehaviorEvent extends Event implements IModBusEvent {
|
||||
public void registerCannonBehavior(@NotNull CannonBehavior behavior) {
|
||||
behavior.register();
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ import net.minecraft.util.Mth;
|
|||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class CannonEntityRenderer extends EntityRenderer<CannonEntity> {
|
||||
public static final ModelLayerLocation MODEL = new ModelLayerLocation(BlastTravelReborn.id("cannon"), "main");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.leisuretimedock.blasttravelreborn.content;
|
||||
|
||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.worldgen.BootstapContext;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.damagesource.DamageScaling;
|
||||
import net.minecraft.world.damagesource.DamageType;
|
||||
|
||||
public class BTRDamageTypes {
|
||||
public static final ResourceKey<DamageType> CANNON = ResourceKey.create(Registries.DAMAGE_TYPE,
|
||||
BlastTravelReborn.id("cannon"));
|
||||
|
||||
public static void bootstrap(BootstapContext<DamageType> context) {
|
||||
context.register(CANNON, new DamageType(
|
||||
"cannon",
|
||||
DamageScaling.WHEN_CAUSED_BY_LIVING_NON_PLAYER,
|
||||
0.0F
|
||||
));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,6 @@ import net.minecraft.client.player.AbstractClientPlayer;
|
|||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
|
|
@ -163,6 +162,11 @@ public class CannonEntity extends Entity {
|
|||
|
||||
@Override
|
||||
public @NotNull InteractionResult interact(@NotNull Player player, @NotNull InteractionHand hand) {
|
||||
ItemStack handItem = player.getItemInHand(hand);
|
||||
// 如果手持火药,填充到大炮中
|
||||
if(!player.isShiftKeyDown()) {
|
||||
if (testAndInteract(player, handItem)) return InteractionResult.sidedSuccess(level().isClientSide());
|
||||
}
|
||||
if (player == this.getFirstPassenger()) {
|
||||
return super.interact(player, hand);
|
||||
}
|
||||
|
|
@ -196,6 +200,90 @@ public class CannonEntity extends Entity {
|
|||
return super.interact(player, hand);
|
||||
}
|
||||
|
||||
private boolean testAndInteract(Player player, @NotNull ItemStack stack) {
|
||||
if (stack.is(Items.GUNPOWDER)) {
|
||||
handlerGunPower(player, stack);
|
||||
return true;
|
||||
} else if (stack.is(Items.CHAIN)) {
|
||||
handlerChain(player, stack);
|
||||
return true;
|
||||
} else if (CannonBehavior.isValidBehaviorStack(stack)) {
|
||||
handlerBehaviorItem(player, stack);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handlerGunPower(Player player, ItemStack stack) {
|
||||
if (!level().isClientSide()) {
|
||||
ItemStack currentGunpowder = inventory.getItem(0);
|
||||
|
||||
// 如果炮内已有火药,先还给玩家
|
||||
if (currentGunpowder.getCount() >= currentGunpowder.getMaxStackSize()) {
|
||||
if (!player.isCreative() && !player.getInventory().add(currentGunpowder)) {
|
||||
// 如果背包满了,掉落在地上
|
||||
player.drop(currentGunpowder, false);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置新的火药到炮中
|
||||
ItemStack newGunpowder = stack.copy();
|
||||
newGunpowder.setCount(currentGunpowder.getCount() + 1); // 只放一个火药
|
||||
((ServerPlayer) player).sendSystemMessage(Component.literal(String.format("%d / %d", currentGunpowder.getCount(), currentGunpowder.getMaxStackSize())), true);
|
||||
inventory.setItem(0, newGunpowder);
|
||||
|
||||
if (!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
|
||||
level().playSound(null, this.blockPosition(), SoundEvents.SAND_PLACE, SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
private void handlerChain(Player player, ItemStack stack) {
|
||||
if (!level().isClientSide()) {
|
||||
ItemStack currentChain = inventory.getItem(2);
|
||||
if (currentChain.isEmpty()) { // 添加锁链
|
||||
ItemStack item = stack.copy();
|
||||
item.setCount(1);
|
||||
inventory.setItem(2, item);
|
||||
if (!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
level().playSound(null, this.blockPosition(), SoundEvents.CHAIN_PLACE, SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||
} else {
|
||||
inventory.setItem(2, ItemStack.EMPTY);
|
||||
if (!player.isCreative()) { // 移除锁链
|
||||
if (!player.getInventory().add(currentChain)) {
|
||||
player.drop(currentChain, false);
|
||||
}
|
||||
}
|
||||
level().playSound(null, this.blockPosition(), SoundEvents.CHAIN_FALL, SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handlerBehaviorItem(Player player, ItemStack stack) {
|
||||
if (!level().isClientSide()) {
|
||||
ItemStack currentBehaviorItem = inventory.getItem(2);
|
||||
if (currentBehaviorItem.isEmpty()) { // 添加物品
|
||||
ItemStack item = stack.copy();
|
||||
item.setCount(1);
|
||||
inventory.setItem(2, item);
|
||||
if (!player.isCreative()) {
|
||||
stack.shrink(1);
|
||||
}
|
||||
level().playSound(null, this.blockPosition(), getBehavior().getPlaceInSound(), SoundSource.BLOCKS, 1.0f, 1.0f);
|
||||
} else {
|
||||
if (stack.is(currentBehaviorItem.getItem())) { //同类物品 +1
|
||||
|
||||
} else { //不同类替换
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipAttackInteraction(@NotNull Entity attacker) {
|
||||
if (attacker instanceof Player player && player != this.getFirstPassenger()) {
|
||||
|
|
@ -299,12 +387,17 @@ public class CannonEntity extends Entity {
|
|||
System.out.println(" - [B]Server: Bounding Box = " + player.getBoundingBox());
|
||||
System.out.println(" - [B]Server: Delta Movement = " + player.getDeltaMovement());
|
||||
}
|
||||
player.stopRiding();
|
||||
((ServerPlayer) player).connection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
|
||||
((ServerPlayer) player).connection.send(new ClientboundSetEntityMotionPacket(player));
|
||||
|
||||
// 关键修改:先设置速度,再停止乘坐
|
||||
player.setDeltaMovement(vel);
|
||||
player.hurtMarked = true;
|
||||
player.hurtMarked = true; // 强制同步运动状态
|
||||
|
||||
// 然后停止乘坐
|
||||
player.stopRiding();
|
||||
|
||||
// 设置飞行状态
|
||||
((PlayerEntityDuck)player).blasttravel$setCannonFlight(true);
|
||||
|
||||
if (!FMLEnvironment.production) {
|
||||
System.out.println(" - [A]Server: Is Passenger = " + player.isPassenger());
|
||||
System.out.println(" - [A]Server: On Ground = " + player.onGround());
|
||||
|
|
@ -315,7 +408,6 @@ public class CannonEntity extends Entity {
|
|||
System.out.println(" - [A]Server: Delta Movement = " + player.getDeltaMovement());
|
||||
}
|
||||
firedPlayer = player;
|
||||
|
||||
}
|
||||
|
||||
this.level().playSound(null, this.blockPosition(), SoundEvents.GENERIC_EXPLODE, SoundSource.BLOCKS, 1, 1);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import com.leisuretimedock.blasttravelreborn.content.entity.CannonEntity;
|
|||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
|
@ -16,13 +18,15 @@ import org.joml.Vector3f;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class CannonBehavior {
|
||||
protected static final Vector3f WHITE = new Vector3f(1, 1, 1);
|
||||
private static final List<CannonBehavior> ID_TO_BEHAVIOR = new ArrayList<>();
|
||||
private static final Object2IntMap<Predicate<ItemStack>> FILTER_TO_BEHAVIOR_ID = new Object2IntOpenHashMap<>();
|
||||
|
||||
private final AtomicBoolean registered = new AtomicBoolean(false);
|
||||
private SoundEvent placeInSound = SoundEvents.SAND_PLACE, takeOutSound = SoundEvents.EMPTY;
|
||||
public final Item icon;
|
||||
public final Predicate<ItemStack> filter;
|
||||
private final ResourceLocation texture;
|
||||
|
|
@ -41,10 +45,28 @@ public class CannonBehavior {
|
|||
this.texture = texture;
|
||||
}
|
||||
|
||||
public CannonBehavior register() {
|
||||
FILTER_TO_BEHAVIOR_ID.put(this.filter, ID_TO_BEHAVIOR.size());
|
||||
ID_TO_BEHAVIOR.add(this);
|
||||
public void setPlaceInSound(SoundEvent placeInSound) {
|
||||
this.placeInSound = placeInSound;
|
||||
}
|
||||
|
||||
public SoundEvent getPlaceInSound() {
|
||||
return placeInSound;
|
||||
}
|
||||
|
||||
public SoundEvent getTakeOutSound() {
|
||||
return takeOutSound;
|
||||
}
|
||||
|
||||
public void setTakeOutSound(SoundEvent takeOutSound) {
|
||||
this.takeOutSound = takeOutSound;
|
||||
}
|
||||
|
||||
public CannonBehavior register() {
|
||||
if (!registered.get()) {
|
||||
FILTER_TO_BEHAVIOR_ID.put(this.filter, ID_TO_BEHAVIOR.size());
|
||||
ID_TO_BEHAVIOR.add(this);
|
||||
registered.set(true);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +108,7 @@ public class CannonBehavior {
|
|||
return texture;
|
||||
}
|
||||
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public ResourceLocation headTexture(CannonEntity entity) {
|
||||
var player = entity.getClientPlayer();
|
||||
|
|
@ -105,4 +128,5 @@ public class CannonBehavior {
|
|||
public @Nullable Vector3f fireColor(CannonEntity entity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package com.leisuretimedock.blasttravelreborn.datagen;
|
||||
|
||||
import com.leisuretimedock.blasttravelreborn.content.BTRDamageTypes;
|
||||
import net.minecraft.core.RegistrySetBuilder;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
|
||||
public class BTRRegistries {
|
||||
public static final RegistrySetBuilder BUILDER = new RegistrySetBuilder()
|
||||
.add(Registries.DAMAGE_TYPE, BTRDamageTypes::bootstrap)
|
||||
;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package com.leisuretimedock.blasttravelreborn.datagen;
|
||||
|
||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||
import com.leisuretimedock.blasttravelreborn.datagen.provider.BTRItemModelProvider;
|
||||
import com.leisuretimedock.blasttravelreborn.datagen.provider.BTRParticleProvider;
|
||||
import com.leisuretimedock.blasttravelreborn.datagen.provider.BTRRecipeProvider;
|
||||
import com.leisuretimedock.blasttravelreborn.datagen.value.BTRLangKeys;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider;
|
||||
import net.minecraftforge.data.event.GatherDataEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import top.r3944realms.lib39.datagen.provider.SimpleLanguageProvider;
|
||||
import top.r3944realms.lib39.datagen.value.McLocale;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = BlastTravelReborn.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public class DataGeneratorHandler {
|
||||
@SubscribeEvent
|
||||
public static void generatorDataEvent(GatherDataEvent event) {
|
||||
LanguageGenerate(event, McLocale.EN_US);
|
||||
LanguageGenerate(event, McLocale.ZH_CN);
|
||||
LanguageGenerate(event, McLocale.ZH_TW);
|
||||
ModelDataGenerate(event);
|
||||
ParticleGenerate(event);
|
||||
RecipeGenerate(event);
|
||||
DatapackBuiltinEntriesGenerate(event);
|
||||
}
|
||||
|
||||
private static void LanguageGenerate(@NotNull GatherDataEvent event, McLocale language) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeClient(),
|
||||
(DataProvider.Factory<SimpleLanguageProvider>) pOutput -> new SimpleLanguageProvider(pOutput, BlastTravelReborn.MOD_ID ,language , BTRLangKeys.INSTANCE)
|
||||
);
|
||||
}
|
||||
private static void ModelDataGenerate(GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeClient(),
|
||||
(DataProvider.Factory<BTRItemModelProvider>) pOutput -> new BTRItemModelProvider(pOutput, event.getExistingFileHelper())
|
||||
);
|
||||
}
|
||||
private static void RecipeGenerate(GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeServer(),
|
||||
(DataProvider.Factory<BTRRecipeProvider>) BTRRecipeProvider::new
|
||||
);
|
||||
}
|
||||
private static void ParticleGenerate(GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeClient(),
|
||||
(DataProvider.Factory<BTRParticleProvider>) pOutput -> new BTRParticleProvider(pOutput, event.getExistingFileHelper())
|
||||
);
|
||||
}
|
||||
private static void DatapackBuiltinEntriesGenerate(GatherDataEvent event) {
|
||||
event.getGenerator().addProvider(
|
||||
event.includeServer(),
|
||||
(DataProvider.Factory<DatapackBuiltinEntriesProvider>) pOutput -> new DatapackBuiltinEntriesProvider(pOutput, event.getLookupProvider(), BTRRegistries.BUILDER, Set.of(BlastTravelReborn.MOD_ID))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.leisuretimedock.blasttravelreborn.datagen.provider;
|
||||
|
||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||
import com.leisuretimedock.blasttravelreborn.content.item.BTRItems;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.client.model.generators.ItemModelProvider;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class BTRItemModelProvider extends ItemModelProvider {
|
||||
public static final String GENERATED = "item/generated";
|
||||
public BTRItemModelProvider(PackOutput packOutput, ExistingFileHelper existingFileHelper) {
|
||||
super(packOutput, BlastTravelReborn.MOD_ID, existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerModels() {
|
||||
itemGeneratedModel(BTRItems.CANNON_ITEM.get(), resourceItem("cannon"));
|
||||
}
|
||||
public void itemGeneratedModel(Item item, ResourceLocation texture) {
|
||||
withExistingParent(itemName(item), GENERATED).texture("layer0", texture);
|
||||
}
|
||||
|
||||
private String itemName(Item item) {
|
||||
return Objects.requireNonNull(ForgeRegistries.ITEMS.getKey(item)).getPath();
|
||||
}
|
||||
|
||||
public ResourceLocation resourceItem(String path) {
|
||||
return BlastTravelReborn.id("item/" + path);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.leisuretimedock.blasttravelreborn.datagen.provider;
|
||||
|
||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||
import com.leisuretimedock.blasttravelreborn.content.BTRParticleTypes;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.common.data.ParticleDescriptionProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BTRParticleProvider extends ParticleDescriptionProvider {
|
||||
|
||||
public BTRParticleProvider(PackOutput output, ExistingFileHelper fileHelper) {
|
||||
super(output, fileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addDescriptions() {
|
||||
List<ResourceLocation> cannonBlastTextures = new ArrayList<>();
|
||||
for (int i = 0; i <= 7; i++){
|
||||
cannonBlastTextures.add(BlastTravelReborn.id("blast_smoke_" + i));
|
||||
}
|
||||
spriteSet(BTRParticleTypes.CANNON_BLAST.get(), cannonBlastTextures);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.leisuretimedock.blasttravelreborn.datagen.provider;
|
||||
|
||||
import com.leisuretimedock.blasttravelreborn.content.item.BTRItems;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.RecipeCategory;
|
||||
import net.minecraft.data.recipes.RecipeProvider;
|
||||
import net.minecraft.data.recipes.ShapedRecipeBuilder;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.item.Items;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class BTRRecipeProvider extends RecipeProvider {
|
||||
public BTRRecipeProvider(PackOutput pOutput) {
|
||||
super(pOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildRecipes(@NotNull Consumer<FinishedRecipe> pWriter) {
|
||||
// 第二个配方(您提供的JSON转换而来)
|
||||
ShapedRecipeBuilder.shaped(RecipeCategory.MISC, BTRItems.CANNON_ITEM.get(), 1)
|
||||
.define('A', Items.IRON_BLOCK)
|
||||
.define('B', Items.STRING)
|
||||
.define('C', ItemTags.STONE_CRAFTING_MATERIALS)
|
||||
.define('D', Items.STICK)
|
||||
.define('E', ItemTags.LOGS)
|
||||
.pattern(" A")
|
||||
.pattern("BA ")
|
||||
.pattern("CDE")
|
||||
.unlockedBy("has_iron_block", has(Items.IRON_BLOCK))
|
||||
.save(pWriter);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package com.leisuretimedock.blasttravelreborn.datagen.value;
|
||||
|
||||
import com.leisuretimedock.blasttravelreborn.BlastTravelReborn;
|
||||
import com.leisuretimedock.blasttravelreborn.content.item.BTRItems;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import top.r3944realms.lib39.datagen.value.ILangKeyValueCollection;
|
||||
import top.r3944realms.lib39.datagen.value.LangKeyValue;
|
||||
import top.r3944realms.lib39.datagen.value.ModPartEnum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public enum BTRLangKeys implements ILangKeyValueCollection {
|
||||
INSTANCE;
|
||||
BTRLangKeys() {
|
||||
initLangKeyValues();
|
||||
}
|
||||
|
||||
final List<LangKeyValue> langKeyValues = new ArrayList<>();
|
||||
public void initLangKeyValues() {
|
||||
addLang(LangKeyValue.ofSupplier(
|
||||
BTRItems.CANNON_ITEM, ModPartEnum.ITEM,
|
||||
"Cannon",
|
||||
"大炮",
|
||||
"大砲",
|
||||
true
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
ModPartEnum.ENTITY.getFullKey(BlastTravelReborn.MOD_ID, "cannon"), ModPartEnum.ENTITY,
|
||||
"Cannon",
|
||||
"大炮",
|
||||
"大砲"
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
"container.blasttravelreborn.cannon_container_menu", ModPartEnum.GUI,
|
||||
"Cannon",
|
||||
"大炮实体",
|
||||
"大砲實體"
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
"death.attack.blasttravelreborn.cannon", ModPartEnum.MESSAGE,
|
||||
"%s was knocked out by a flying %s",
|
||||
"%s被飞行的%s击倒了",
|
||||
"%s被飛行的%s擊倒了"
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
"dialog.blasttravelreborn.full_cannon", ModPartEnum.MESSAGE,
|
||||
"Cannon is full!",
|
||||
"大炮已装满!",
|
||||
"大砲已裝滿!"
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
"dialog.blasttravelreborn.no_gunpowder", ModPartEnum.MESSAGE,
|
||||
"Cannon has no gunpowder!",
|
||||
"大炮没有火药了!",
|
||||
"大砲沒有火藥了!"
|
||||
));
|
||||
addLang(LangKeyValue.ofKey(
|
||||
"mount.blasttravelreborn.cannon.onboard", ModPartEnum.MESSAGE,
|
||||
"Press %s to Exit, or %s to Fire",
|
||||
"按%s离开,或按%s发射",
|
||||
"按%s離開,或按%s發射"
|
||||
));
|
||||
}
|
||||
|
||||
public void addLang(LangKeyValue keyValue) {
|
||||
langKeyValues.add(keyValue);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
langKeyValues.clear();
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
@Override
|
||||
public @Unmodifiable List<LangKeyValue> getValues() {
|
||||
return List.copyOf(langKeyValues);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@ package com.leisuretimedock.blasttravelreborn.network.toClient;
|
|||
|
||||
import com.leisuretimedock.blasttravelreborn.content.entity.CannonEntity;
|
||||
import com.leisuretimedock.blasttravelreborn.util.PlayerEntityDuck;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
|
@ -40,45 +39,35 @@ public record FireCannonPayload(int cannonId, Optional<Integer> launchedId, doub
|
|||
}
|
||||
public void handler(Supplier<NetworkEvent.Context> ctx) {
|
||||
NetworkEvent.Context context = ctx.get();
|
||||
if(context.getNetworkManager().getPacketListener() instanceof ClientPacketListener clientPacketListener) {
|
||||
if (context.getNetworkManager().getPacketListener() instanceof ClientPacketListener clientPacketListener) {
|
||||
context.enqueueWork(() -> {
|
||||
if(hasPlayer()) {
|
||||
//noinspection OptionalGetWithoutIsPresent
|
||||
if (hasPlayer()) {
|
||||
if (clientPacketListener.getLevel().getEntity(launchedId.get()) instanceof Player launchedPlayer) {
|
||||
// 记录发射前状态
|
||||
if (!FMLEnvironment.production) {
|
||||
System.out.println(" - [B]Client: Is Passenger = " + launchedPlayer.isPassenger());
|
||||
System.out.println(" - [B]Client: On Ground = " + launchedPlayer.onGround());
|
||||
System.out.println(" - [B]Client: noPhysics =" + launchedPlayer.noPhysics);
|
||||
System.out.println(" - [B]Client: Pose = " + launchedPlayer.getPose());
|
||||
System.out.println(" - [B]Client: riding entity = " + launchedPlayer.getVehicle());
|
||||
System.out.println(" - [B]Client: Bounding Box = " + launchedPlayer.getBoundingBox());
|
||||
System.out.println(" - [B]Client: Delta Movement = " + launchedPlayer.getDeltaMovement());
|
||||
}
|
||||
|
||||
// 立即停止乘坐并设置速度
|
||||
if (launchedPlayer.isPassenger()) {
|
||||
launchedPlayer.stopRiding();
|
||||
}
|
||||
|
||||
// 延迟一个 tick 执行飞行初始化逻辑
|
||||
Minecraft.getInstance().tell(() -> {
|
||||
// 此时已脱离炮台,设置速度
|
||||
launchedPlayer.getAbilities().flying = false;
|
||||
launchedPlayer.setPos(launchedPlayer.getX(), launchedPlayer.getY(), launchedPlayer.getZ());
|
||||
launchedPlayer.setDeltaMovement(velocityX, velocityY, velocityZ);
|
||||
((PlayerEntityDuck) launchedPlayer).blasttravel$setCannonFlight(true);
|
||||
// 直接设置速度,不要延迟
|
||||
launchedPlayer.setDeltaMovement(velocityX, velocityY, velocityZ);
|
||||
launchedPlayer.hurtMarked = true; // 强制同步运动
|
||||
((PlayerEntityDuck) launchedPlayer).blasttravel$setCannonFlight(true);
|
||||
|
||||
// 输出变更后状态
|
||||
if (!FMLEnvironment.production) {
|
||||
System.out.println(" - [A]Client: Is Passenger = " + launchedPlayer.isPassenger());
|
||||
System.out.println(" - [A]Client: On Ground = " + launchedPlayer.onGround());
|
||||
System.out.println(" - [A]Client: noPhysics = " + launchedPlayer.noPhysics);
|
||||
System.out.println(" - [A]Client: Pose = " + launchedPlayer.getPose());
|
||||
System.out.println(" - [A]Client: riding entity = " + launchedPlayer.getVehicle());
|
||||
System.out.println(" - [A]Client: Bounding Box = " + launchedPlayer.getBoundingBox());
|
||||
System.out.println(" - [A]Client: Delta Movement = " + launchedPlayer.getDeltaMovement());
|
||||
}
|
||||
});
|
||||
// 记录发射后状态
|
||||
if (!FMLEnvironment.production) {
|
||||
System.out.println(" - [A]Client: Is Passenger = " + launchedPlayer.isPassenger());
|
||||
System.out.println(" - [A]Client: Delta Movement = " + launchedPlayer.getDeltaMovement());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理炮实体效果
|
||||
Entity entity = clientPacketListener.getLevel().getEntity(cannonId);
|
||||
if (entity instanceof CannonEntity cannonEntity) {
|
||||
cannonEntity.fireClient();
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@ import net.minecraftforge.network.NetworkEvent;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
public record StopCannonFlightClientPayload(int flyingId) {
|
||||
public StopCannonFlightClientPayload(FriendlyByteBuf buf) {
|
||||
this(buf.readInt());
|
||||
}
|
||||
public StopCannonFlightClientPayload(Player flying) {
|
||||
this(flying.getId());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ public record RequestFirePayload(int cannonId) {
|
|||
public RequestFirePayload(CannonEntity cannonEntity) {
|
||||
this(cannonEntity.getId());
|
||||
}
|
||||
public RequestFirePayload(FriendlyByteBuf buf) {
|
||||
this(buf.readInt());
|
||||
}
|
||||
|
||||
public void write(FriendlyByteBuf buf) {
|
||||
buf.writeInt(cannonId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,12 @@ versionRange = "${minecraft_version_range}"
|
|||
ordering = "NONE"
|
||||
side = "BOTH"
|
||||
[[dependencies."${mod_id}"]]
|
||||
versionRange = "[0.2.1+1.20-fabrge,)"
|
||||
versionRange = "[0.2.3,)"
|
||||
modId = "jsonem"
|
||||
mandatory = false
|
||||
side = "CLIENT"
|
||||
[[dependencies."${mod_id}"]]
|
||||
versionRange = "[0.0.17,)"
|
||||
modId = "lib39"
|
||||
mandatory = false
|
||||
side = "BOTH"
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"container.blasttravelreborn.cannon_container_menu": "Cannon",
|
||||
"item.blasttravelreborn.cannon": "Cannon",
|
||||
"entity.blasttravelreborn.cannon": "Cannon",
|
||||
|
||||
"death.attack.blasttravelreborn.cannon": "%s was knocked out by a flying %s",
|
||||
"dialog.blasttravelreborn.full_cannon": "Cannon is full!",
|
||||
"dialog.blasttravelreborn.no_gunpowder": "Cannon has no gunpowder!",
|
||||
"mount.blasttravelreborn.cannon.onboard": "Press %s to Exit, or %s to Fire"
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "blasttravelreborn:item/cannon"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"textures": [
|
||||
"blasttravelreborn:blast_smoke_0",
|
||||
"blasttravelreborn:blast_smoke_1",
|
||||
"blasttravelreborn:blast_smoke_2",
|
||||
"blasttravelreborn:blast_smoke_3",
|
||||
"blasttravelreborn:blast_smoke_4",
|
||||
"blasttravelreborn:blast_smoke_5",
|
||||
"blasttravelreborn:blast_smoke_6",
|
||||
"blasttravelreborn:blast_smoke_7",
|
||||
"blasttravelreborn:blast_smoke_8"
|
||||
]
|
||||
}
|
||||
|
|
@ -6,10 +6,10 @@
|
|||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"LivingEntityAccess",
|
||||
"PlayerEntityMixin",
|
||||
"PlayerEntityMixinClient"
|
||||
"PlayerEntityMixin"
|
||||
],
|
||||
"client": [
|
||||
"PlayerEntityMixinClient",
|
||||
"ClientPlayerEntityMixin",
|
||||
"ClientPlayNetworkHandlerMixin",
|
||||
"PlayerEntityModelMixin",
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"pattern": [
|
||||
" A",
|
||||
"BA ",
|
||||
"CDE"
|
||||
],
|
||||
"key": {
|
||||
"A": {"item": "minecraft:iron_block"},
|
||||
"B": {"item": "minecraft:string"},
|
||||
"C": {"tag": "minecraft:stone_crafting_materials"},
|
||||
"D": {"item": "minecraft:stick"},
|
||||
"E": {"tag": "minecraft:logs"}
|
||||
},
|
||||
"result": {
|
||||
"item": "blasttravelreborn:cannon",
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user