diff --git a/common/src/generated/resources/.cache/59eb3dbb5f86130e09b3c62d89b9525ee01cf52d b/common/src/generated/resources/.cache/59eb3dbb5f86130e09b3c62d89b9525ee01cf52d index 0bcda039..28991024 100644 --- a/common/src/generated/resources/.cache/59eb3dbb5f86130e09b3c62d89b9525ee01cf52d +++ b/common/src/generated/resources/.cache/59eb3dbb5f86130e09b3c62d89b9525ee01cf52d @@ -1,4 +1,4 @@ -// 1.21.1 2024-11-30T14:43:00.0255867 Loot Tables +// 1.21.1 2024-12-07T18:13:58.7388566 Loot Tables 2b18f4ee4964de853f965809175e41672c73f2a3 data/eternal_starlight/loot_table/blocks/abyssal_fire.json 188b8614ef4815c81bb45c3a918877795892cf25 data/eternal_starlight/loot_table/blocks/abyssal_geyser.json 77967e1af1e01fc2bbf8f97dd52c510df8648a4c data/eternal_starlight/loot_table/blocks/abyssal_kelp.json @@ -586,6 +586,7 @@ a17c39e100a98bcc3ecff5dd8c27bed6ec49668c data/eternal_starlight/loot_table/chest a461217c956af4bd0fb8803afa168aeb4b966da2 data/eternal_starlight/loot_table/entities/astral_golem.json 7f94abc7aae330ee290d6e0d4ee4b67e4bab1f18 data/eternal_starlight/loot_table/entities/aurora_deer.json fa0d1dceaeb0277bfa61ee74b03cfbe13644ee9c data/eternal_starlight/loot_table/entities/boarwarf.json +00afab123f954ff548d0c8db1f3322e7d81b1125 data/eternal_starlight/loot_table/entities/creteor.json 691a8bff1f5eeba0b472628916c6f0f9338c0260 data/eternal_starlight/loot_table/entities/crystallized_moth.json 033f6a38e81118db10ee4cfd3e493dab70af077e data/eternal_starlight/loot_table/entities/ent.json 82c62a4f1841005f4c3c51c8078024d142da2c06 data/eternal_starlight/loot_table/entities/freeze.json @@ -604,5 +605,6 @@ cdfda6f90f96ac9dd5c8997e86411f844ff69411 data/eternal_starlight/loot_table/entit babe6abda538bda4948feaa3bb8d8965deff0d8b data/eternal_starlight/loot_table/entities/tangled_skull.json b01bfc5a45f772ef5c880ced1d46e07c8a9613f6 data/eternal_starlight/loot_table/entities/the_gatekeeper.json 5d9a6a5389e54faca2c0597fa733a5a68ac14490 data/eternal_starlight/loot_table/entities/thirst_walker.json +8a2b1fc489213ee3656ebe2340512ccb70b4b991 data/eternal_starlight/loot_table/entities/tiny_creteor.json 9742c2717dc30701fa79d4ab3d735a2201afc8b9 data/eternal_starlight/loot_table/entities/twilight_gaze.json 2e639dab65828cba17fb69870b07c99a66201724 data/eternal_starlight/loot_table/entities/yeti.json diff --git a/common/src/generated/resources/.cache/735031f3addf80804addae5e3f53249900116f1e b/common/src/generated/resources/.cache/735031f3addf80804addae5e3f53249900116f1e index 88d0c185..8e0c90f6 100644 --- a/common/src/generated/resources/.cache/735031f3addf80804addae5e3f53249900116f1e +++ b/common/src/generated/resources/.cache/735031f3addf80804addae5e3f53249900116f1e @@ -1,2 +1,2 @@ -// 1.21.1 2024-11-17T14:36:09.2472511 Sound Definitions -a1261f8ceb7c165ba55dde15a14a105ac86ea5b0 assets/eternal_starlight/sounds.json +// 1.21.1 2024-12-08T15:27:10.7369329 Sound Definitions +b96fd1377a2af53fad5e8542582bc0249e73c9f2 assets/eternal_starlight/sounds.json diff --git a/common/src/generated/resources/.cache/894d7d52e72304edfd08d72006a0a8d7ab469d4d b/common/src/generated/resources/.cache/894d7d52e72304edfd08d72006a0a8d7ab469d4d index 95317c42..33d7d8ae 100644 --- a/common/src/generated/resources/.cache/894d7d52e72304edfd08d72006a0a8d7ab469d4d +++ b/common/src/generated/resources/.cache/894d7d52e72304edfd08d72006a0a8d7ab469d4d @@ -1,4 +1,4 @@ -// 1.21.1 2024-09-22T12:17:42.3914069 Tags for minecraft:entity_type mod id eternal_starlight +// 1.21.1 2024-12-07T18:13:58.7713914 Tags for minecraft:entity_type mod id eternal_starlight 5466319e12aea1f42139ac09c8ffdd0620c716d0 data/c/tags/entity_type/boats.json d44f14633b66cf9ee5f04c1bb297ee340a53e288 data/c/tags/entity_type/bosses.json 7c4a83216410b5cc42cab8c49f3ef1afb4bb9ebc data/eternal_starlight/tags/entity_type/abyssal_fire_immune.json @@ -9,7 +9,7 @@ be4ff0376ac9ff8a51eab4ae581131fd7b545de1 data/eternal_starlight/tags/entity_type 7c4a83216410b5cc42cab8c49f3ef1afb4bb9ebc data/minecraft/tags/entity_type/aquatic.json 71a6499c4764a81cc18b7b21fea1d988e578a0b6 data/minecraft/tags/entity_type/arrows.json 3f853abb02779d1f23df9823ebb9d8707f24ddc9 data/minecraft/tags/entity_type/arthropod.json -5459e6dcff656af9ac3c0cbea22ffdabcbea8451 data/minecraft/tags/entity_type/fall_damage_immune.json +d8ee7cf341d31cccb0314d84c97e3e6567b95b60 data/minecraft/tags/entity_type/fall_damage_immune.json f6eb1b878dcda83e8e0f0c5388c37999f2e0ec47 data/minecraft/tags/entity_type/freeze_immune_entity_types.json f627b828af90e448f9c5322878730dddd94748ff data/minecraft/tags/entity_type/immune_to_infested.json 81a6c1860d98805184066dd01894829e9b9830ec data/minecraft/tags/entity_type/skeletons.json diff --git a/common/src/generated/resources/.cache/9539076883c29777f26a3c22ea17f026ade8d9e9 b/common/src/generated/resources/.cache/9539076883c29777f26a3c22ea17f026ade8d9e9 index 3ebc7d98..3b81126d 100644 --- a/common/src/generated/resources/.cache/9539076883c29777f26a3c22ea17f026ade8d9e9 +++ b/common/src/generated/resources/.cache/9539076883c29777f26a3c22ea17f026ade8d9e9 @@ -1,4 +1,4 @@ -// 1.21.1 2024-11-30T14:43:00.0455465 Item Models: eternal_starlight +// 1.21.1 2024-12-07T18:13:58.7713914 Item Models: eternal_starlight f36b77087c8c68017703cd72753faa9ec0bb05c9 assets/eternal_starlight/models/item/abyssal_fruit.json 566abbb0b7c88c3e62953e9a59a3c7a789481e57 assets/eternal_starlight/models/item/abyssal_geyser.json 22602a3404b600eeca3221ff2689c59995af1cfc assets/eternal_starlight/models/item/abyssal_magma_block.json @@ -132,6 +132,7 @@ df345951415b24130c20856f2bf494de8d88b12d assets/eternal_starlight/models/item/co 6c070c5d2e1c3e3ba28da6d35951d30ed3002f72 assets/eternal_starlight/models/item/crescent_grass.json fdeb72c584a345e6f78e9485ec853167b91fe994 assets/eternal_starlight/models/item/crescent_spear_inventory.json 11a7930fa3222c7e64695591eb194674ef73f689 assets/eternal_starlight/models/item/crest_pot.json +63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/eternal_starlight/models/item/creteor_spawn_egg.json 7ddb335c47119122e79dafb94614bce46cc11f57 assets/eternal_starlight/models/item/cryobyssal_geyser.json eef40b64a1a8177cdce1c93254c22981bf00b872 assets/eternal_starlight/models/item/cryobyssal_magma_block.json de3ad123be78b147a98def85368f2af88ed5998a assets/eternal_starlight/models/item/cryobysslate.json @@ -741,6 +742,7 @@ b4174b32eb5673b2be7d048ce1e020dcd4312ba2 assets/eternal_starlight/models/item/th b2f430a6538d191a2c7d44af4480699ba9af85d9 assets/eternal_starlight/models/item/thioquartz_cluster.json bcac9ea3811d191e509e7a4d7c296cee003bee81 assets/eternal_starlight/models/item/thioquartz_shard.json 63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/eternal_starlight/models/item/thirst_walker_spawn_egg.json +63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/eternal_starlight/models/item/tiny_creteor_spawn_egg.json 8156bb59db943a8a00cc701a3ffde7a85278cf13 assets/eternal_starlight/models/item/tooth_of_hunger.json 9f984c8f3b39db9dbeed2eddb4d529c4715aadc6 assets/eternal_starlight/models/item/tooth_of_hunger_tiles.json 2002489b9dee5d09595beb4b9b6d28e3f31f7c0f assets/eternal_starlight/models/item/tooth_of_hunger_tile_slab.json diff --git a/common/src/generated/resources/.cache/b5294eda5c650593108e068003e23d389cc35af6 b/common/src/generated/resources/.cache/b5294eda5c650593108e068003e23d389cc35af6 index 0c9a796e..c151048d 100644 --- a/common/src/generated/resources/.cache/b5294eda5c650593108e068003e23d389cc35af6 +++ b/common/src/generated/resources/.cache/b5294eda5c650593108e068003e23d389cc35af6 @@ -1,4 +1,4 @@ -// 1.21.1 2024-08-27T17:30:58.3550552 Particle Descriptions +// 1.21.1 2024-12-07T23:32:10.2615466 Particle Descriptions 2fa6b966de82cbc7de1510007ab8640a9d8092d4 assets/eternal_starlight/particles/advanced_glow.json 70487e0406f4fbc40c6a147fb14954dbd60cd7e1 assets/eternal_starlight/particles/aethersent_smoke.json 80f29c59edeb07d57852a74a160b7619e049c7a4 assets/eternal_starlight/particles/amaramber_flame.json @@ -7,6 +7,7 @@ df3620b4fc75de9ed119c43b5b58474f5bc41607 assets/eternal_starlight/particles/blad 5e60548fdce546847dadbb84ecb3a63b05c8a406 assets/eternal_starlight/particles/crystallized_moth_sonar.json 641c77c49f4a8a1145185d4910cb1ef687c6e990 assets/eternal_starlight/particles/energy.json 9a22fb5355c86494e5b317774a2fc4f96dc39212 assets/eternal_starlight/particles/explosion.json +020dd7cd4a3a4ade5dbf5ba631b9db43cb42e25d assets/eternal_starlight/particles/explosion_shock.json 5a3c2a2d77325bc3956bce6114ce7e57252db781 assets/eternal_starlight/particles/firefly.json 2fa6b966de82cbc7de1510007ab8640a9d8092d4 assets/eternal_starlight/particles/glow.json 58aff6c09e81b4e3406646bfc889267a76b2d6a6 assets/eternal_starlight/particles/ring_explosion.json diff --git a/common/src/generated/resources/assets/eternal_starlight/models/item/creteor_spawn_egg.json b/common/src/generated/resources/assets/eternal_starlight/models/item/creteor_spawn_egg.json new file mode 100644 index 00000000..d1aaa9d6 --- /dev/null +++ b/common/src/generated/resources/assets/eternal_starlight/models/item/creteor_spawn_egg.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/eternal_starlight/models/item/tiny_creteor_spawn_egg.json b/common/src/generated/resources/assets/eternal_starlight/models/item/tiny_creteor_spawn_egg.json new file mode 100644 index 00000000..d1aaa9d6 --- /dev/null +++ b/common/src/generated/resources/assets/eternal_starlight/models/item/tiny_creteor_spawn_egg.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/eternal_starlight/particles/explosion_shock.json b/common/src/generated/resources/assets/eternal_starlight/particles/explosion_shock.json new file mode 100644 index 00000000..e38e08e4 --- /dev/null +++ b/common/src/generated/resources/assets/eternal_starlight/particles/explosion_shock.json @@ -0,0 +1,5 @@ +{ + "textures": [ + "eternal_starlight:explosion_shock" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/eternal_starlight/sounds.json b/common/src/generated/resources/assets/eternal_starlight/sounds.json index 1c7756d1..b7a24305 100644 --- a/common/src/generated/resources/assets/eternal_starlight/sounds.json +++ b/common/src/generated/resources/assets/eternal_starlight/sounds.json @@ -173,6 +173,39 @@ ], "subtitle": "subtitles.entity.eternal_starlight.boarwarf.yes" }, + "entity.creteor.charge": { + "sounds": [ + "eternal_starlight:mob/creteor/charge" + ], + "subtitle": "subtitles.entity.eternal_starlight.creteor.charge" + }, + "entity.creteor.death": { + "sounds": [ + "eternal_starlight:mob/creteor/death" + ], + "subtitle": "subtitles.entity.eternal_starlight.creteor.death" + }, + "entity.creteor.explode": { + "sounds": [ + "eternal_starlight:mob/creteor/explode" + ], + "subtitle": "subtitles.entity.eternal_starlight.creteor.explode" + }, + "entity.creteor.hurt": { + "sounds": [ + "eternal_starlight:mob/creteor/hurt1", + "eternal_starlight:mob/creteor/hurt2", + "eternal_starlight:mob/creteor/hurt3", + "eternal_starlight:mob/creteor/hurt4" + ], + "subtitle": "subtitles.entity.eternal_starlight.creteor.hurt" + }, + "entity.creteor.roll": { + "sounds": [ + "eternal_starlight:mob/creteor/roll" + ], + "subtitle": "subtitles.entity.eternal_starlight.creteor.roll" + }, "entity.ent.hurt": { "sounds": [ "eternal_starlight:mob/ent/hurt" diff --git a/common/src/generated/resources/data/eternal_starlight/loot_table/entities/creteor.json b/common/src/generated/resources/data/eternal_starlight/loot_table/entities/creteor.json new file mode 100644 index 00000000..f1a23f6b --- /dev/null +++ b/common/src/generated/resources/data/eternal_starlight/loot_table/entities/creteor.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:entity", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 5.0, + "min": 3.0 + }, + "function": "minecraft:set_count" + }, + { + "count": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + }, + "enchantment": "minecraft:looting", + "function": "minecraft:enchanted_count_increase" + } + ], + "name": "eternal_starlight:raw_aethersent" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "eternal_starlight:entities/creteor" +} \ No newline at end of file diff --git a/common/src/generated/resources/data/eternal_starlight/loot_table/entities/tiny_creteor.json b/common/src/generated/resources/data/eternal_starlight/loot_table/entities/tiny_creteor.json new file mode 100644 index 00000000..e91cdc9d --- /dev/null +++ b/common/src/generated/resources/data/eternal_starlight/loot_table/entities/tiny_creteor.json @@ -0,0 +1,36 @@ +{ + "type": "minecraft:entity", + "pools": [ + { + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "add": false, + "count": { + "type": "minecraft:uniform", + "max": 3.0, + "min": 1.0 + }, + "function": "minecraft:set_count" + }, + { + "count": { + "type": "minecraft:uniform", + "max": 1.0, + "min": 0.0 + }, + "enchantment": "minecraft:looting", + "function": "minecraft:enchanted_count_increase" + } + ], + "name": "eternal_starlight:raw_aethersent" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "eternal_starlight:entities/tiny_creteor" +} \ No newline at end of file diff --git a/common/src/generated/resources/data/minecraft/tags/entity_type/fall_damage_immune.json b/common/src/generated/resources/data/minecraft/tags/entity_type/fall_damage_immune.json index 804a771c..ba2349a2 100644 --- a/common/src/generated/resources/data/minecraft/tags/entity_type/fall_damage_immune.json +++ b/common/src/generated/resources/data/minecraft/tags/entity_type/fall_damage_immune.json @@ -1,6 +1,8 @@ { "values": [ "eternal_starlight:astral_golem", + "eternal_starlight:creteor", + "eternal_starlight:tiny_creteor", "eternal_starlight:crystallized_moth", "eternal_starlight:shimmer_lacewing", "eternal_starlight:grimstone_golem" diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/handler/ClientSetupHandlers.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/handler/ClientSetupHandlers.java index 3dd8705a..92edb304 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/handler/ClientSetupHandlers.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/handler/ClientSetupHandlers.java @@ -593,6 +593,7 @@ public static void registerParticleProviders(ParticleProviderRegisterStrategy st strategy.register(ESParticles.SMOKE_TRAIL.get(), SmokeTrailParticle.Provider::new); strategy.register(ESParticles.AETHERSENT_EXPLOSION.get(), AethersentExplosionParticle.Provider::new); strategy.register(ESParticles.ASHEN_SNOW.get(), AshenSnowParticle.Provider::new); + strategy.register(ESParticles.EXPLOSION_SHOCK.get(), ExplosionShockParticle.Provider::new); strategy.register(ESParticles.ADVANCED_GLOW.get(), AdvancedParticle.Provider::new); strategy.register(ESParticles.SHINE.get(), AdvancedParticle.Provider::new); } @@ -631,6 +632,8 @@ public static void registerEntityRenderers(EntityRendererRegisterStrategy strate strategy.register(ESEntities.LONESTAR_SKELETON.get(), LonestarSkeletonRenderer::new); strategy.register(ESEntities.NIGHTFALL_SPIDER.get(), NightfallSpiderRenderer::new); strategy.register(ESEntities.THIRST_WALKER.get(), ThirstWalkerRenderer::new); + strategy.register(ESEntities.CRETEOR.get(), CreteorRenderer::new); + strategy.register(ESEntities.TINY_CRETEOR.get(), TinyCreteorRenderer::new); strategy.register(ESEntities.ENT.get(), EntRenderer::new); strategy.register(ESEntities.RATLIN.get(), RatlinRenderer::new); strategy.register(ESEntities.YETI.get(), YetiRenderer::new); @@ -700,6 +703,10 @@ public static void registerLayers(RendererLayerRegisterStrategy strategy) { strategy.register(LonestarSkeletonRenderer.LONESTAR_OUTER_ARMOR, () -> LayerDefinition.create(HumanoidArmorModel.createBodyLayer(INNER_ARMOR_DEFORMATION), 64, 32)); strategy.register(NightfallSpiderModel.LAYER_LOCATION, NightfallSpiderModel::createBodyLayer); strategy.register(ThirstWalkerModel.LAYER_LOCATION, ThirstWalkerModel::createBodyLayer); + strategy.register(CreteorModel.LAYER_LOCATION, () -> CreteorModel.createBodyLayer(CubeDeformation.NONE)); + strategy.register(CreteorModel.ARMOR_LOCATION, () -> CreteorModel.createBodyLayer(new CubeDeformation(2.0f))); + strategy.register(TinyCreteorModel.LAYER_LOCATION, () -> TinyCreteorModel.createBodyLayer(CubeDeformation.NONE)); + strategy.register(TinyCreteorModel.ARMOR_LOCATION, () -> TinyCreteorModel.createBodyLayer(new CubeDeformation(2.0f))); strategy.register(EntModel.LAYER_LOCATION, EntModel::createBodyLayer); strategy.register(RatlinModel.LAYER_LOCATION, RatlinModel::createBodyLayer); strategy.register(YetiModel.LAYER_LOCATION, YetiModel::createBodyLayer); diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/animation/definition/CreteorAnimation.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/animation/definition/CreteorAnimation.java new file mode 100644 index 00000000..81affbf0 --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/animation/definition/CreteorAnimation.java @@ -0,0 +1,45 @@ +package cn.leolezury.eternalstarlight.common.client.model.animation.definition; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.animation.AnimationChannel; +import net.minecraft.client.animation.AnimationDefinition; +import net.minecraft.client.animation.Keyframe; +import net.minecraft.client.animation.KeyframeAnimations; + +@Environment(EnvType.CLIENT) +public class CreteorAnimation { + public static final AnimationDefinition IDLE = AnimationDefinition.Builder.withLength(10.0F).looping() + .addAnimation("root", new AnimationChannel(AnimationChannel.Targets.POSITION, + new Keyframe(0.0F, KeyframeAnimations.posVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(5.0F, KeyframeAnimations.posVec(0.0F, -0.5F, 0.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(10.0F, KeyframeAnimations.posVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM) + )) + .addAnimation("right_leg", new AnimationChannel(AnimationChannel.Targets.ROTATION, + new Keyframe(0.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(5.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 5.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(10.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM) + )) + .addAnimation("right_leg", new AnimationChannel(AnimationChannel.Targets.POSITION, + new Keyframe(10.0F, KeyframeAnimations.posVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM) + )) + .addAnimation("left_leg", new AnimationChannel(AnimationChannel.Targets.ROTATION, + new Keyframe(0.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(5.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, -5.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(10.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM) + )) + .addAnimation("left_leg", new AnimationChannel(AnimationChannel.Targets.POSITION, + new Keyframe(10.0F, KeyframeAnimations.posVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM) + )) + .addAnimation("right_arm", new AnimationChannel(AnimationChannel.Targets.ROTATION, + new Keyframe(0.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(5.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 5.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(10.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM) + )) + .addAnimation("left_arm", new AnimationChannel(AnimationChannel.Targets.ROTATION, + new Keyframe(0.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(5.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, -5.0F), AnimationChannel.Interpolations.CATMULLROM), + new Keyframe(10.0F, KeyframeAnimations.degreeVec(0.0F, 0.0F, 0.0F), AnimationChannel.Interpolations.CATMULLROM) + )) + .build(); +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/entity/CreteorModel.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/entity/CreteorModel.java new file mode 100644 index 00000000..e4113a2d --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/entity/CreteorModel.java @@ -0,0 +1,78 @@ +package cn.leolezury.eternalstarlight.common.client.model.entity; + +import cn.leolezury.eternalstarlight.common.EternalStarlight; +import cn.leolezury.eternalstarlight.common.client.model.animation.AnimatedEntityModel; +import cn.leolezury.eternalstarlight.common.client.model.animation.definition.CreteorAnimation; +import cn.leolezury.eternalstarlight.common.entity.living.monster.Creteor; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.util.Mth; + +@Environment(EnvType.CLIENT) +public class CreteorModel extends AnimatedEntityModel { + public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(EternalStarlight.id("creteor"), "main"); + public static final ModelLayerLocation ARMOR_LOCATION = new ModelLayerLocation(EternalStarlight.id("creteor"), "armor"); + private final ModelPart root; + private final ModelPart rotator; + + public CreteorModel(ModelPart root) { + this.root = root.getChild("root"); + this.rotator = root.getChild("root").getChild("rotator"); + } + + public static LayerDefinition createBodyLayer(CubeDeformation deformation) { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition root = partdefinition.addOrReplaceChild("root", CubeListBuilder.create(), PartPose.offset(0.0F, 12.0F, 0.0F)); + + PartDefinition rotator = root.addOrReplaceChild("rotator", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -12.0F, -3.0F, 8.0F, 16.0F, 6.0F, deformation), PartPose.offset(0.0F, 0.0F, 0.0F)); + + PartDefinition crystal1 = rotator.addOrReplaceChild("crystal1", CubeListBuilder.create().texOffs(29, 1).addBox(-6.0F, -6.0F, 0.0F, 10.0F, 10.0F, 0.0F, deformation), PartPose.offset(-4.0F, -12.0F, 0.0F)); + + crystal1.addOrReplaceChild("crystal2", CubeListBuilder.create().texOffs(29, 12).addBox(-4.5F, -4.0F, 0.0F, 9.0F, 8.0F, 0.0F, deformation), PartPose.offsetAndRotation(-2.0F, -2.0F, 0.0F, 0.0F, -1.5708F, -0.7854F)); + + PartDefinition crystal3 = rotator.addOrReplaceChild("crystal3", CubeListBuilder.create(), PartPose.offsetAndRotation(3.0F, -6.0F, 1.0F, 0.0F, 0.0F, -0.2618F)); + + crystal3.addOrReplaceChild("crystal4", CubeListBuilder.create().texOffs(25, 21).mirror().addBox(0.0F, 0.0F, 0.0F, 4.0F, 0.0F, 4.0F, deformation).mirror(false), PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, 0.0F, 0.7854F, 0.0F)); + + crystal3.addOrReplaceChild("crystal5", CubeListBuilder.create().texOffs(25, 21).mirror().addBox(0.0F, 0.0F, 0.0F, 4.0F, 0.0F, 4.0F, deformation).mirror(false), PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, -1.5708F, 0.0F, -0.7854F)); + + rotator.addOrReplaceChild("crystal6", CubeListBuilder.create().texOffs(29, 26).addBox(-2.5F, -4.0F, 0.0F, 5.0F, 4.0F, 0.0F, deformation), PartPose.offsetAndRotation(4.0F, -6.0F, -2.0F, -0.4363F, 0.0F, 1.5708F)); + + PartDefinition leftLeg = rotator.addOrReplaceChild("left_leg", CubeListBuilder.create().texOffs(20, 46).addBox(-0.5F, -2.0F, -2.5F, 5.0F, 10.0F, 5.0F, deformation), PartPose.offsetAndRotation(0.5F, 4.0F, 0.0F, 0.0F, 0.0F, -0.2138F)); + + leftLeg.addOrReplaceChild("crystal8", CubeListBuilder.create().texOffs(25, 21).mirror().addBox(0.0F, 0.0F, 0.0F, 4.0F, 0.0F, 4.0F, deformation).mirror(false), PartPose.offsetAndRotation(3.5F, 3.0F, 0.0F, 1.5708F, 0.0F, 0.3927F)); + + PartDefinition rightLeg = rotator.addOrReplaceChild("right_leg", CubeListBuilder.create().texOffs(0, 46).addBox(-4.5F, -2.0F, -2.5F, 5.0F, 10.0F, 5.0F, deformation), PartPose.offsetAndRotation(-0.5F, 4.0F, 0.0F, 0.0F, 0.0F, 0.2138F)); + + rightLeg.addOrReplaceChild("crystal7", CubeListBuilder.create().texOffs(29, 26).mirror().addBox(-4.0F, -4.0F, 0.0F, 5.0F, 4.0F, 0.0F, deformation).mirror(false), PartPose.offsetAndRotation(-4.5F, 4.0F, 0.0F, 0.4363F, 0.0F, -1.5708F)); + + rotator.addOrReplaceChild("left_arm", CubeListBuilder.create().texOffs(0, 34).addBox(0.0F, -3.0F, 0.0F, 8.0F, 6.0F, 6.0F, deformation), PartPose.offset(4.0F, -1.0F, -3.0F)); + + rotator.addOrReplaceChild("right_arm", CubeListBuilder.create().texOffs(0, 22).addBox(-8.0F, -3.0F, 0.0F, 8.0F, 6.0F, 6.0F, deformation), PartPose.offset(-4.0F, -1.0F, -3.0F)); + + return LayerDefinition.create(meshdefinition, 64, 64); + } + + @Override + public void setupAnim(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + this.root().getAllParts().forEach(ModelPart::resetPose); + this.animate(entity.idleAnimationState, CreteorAnimation.IDLE, ageInTicks); + rotator.xRot = -90 * Mth.DEG_TO_RAD; + rotator.zRot = 90 * Mth.DEG_TO_RAD; + rotator.yRot = -(Mth.rotLerp(Mth.frac(ageInTicks), entity.prevRollAngle, entity.rollAngle) + 90) * Mth.DEG_TO_RAD; + if (entity.getSwell() >= 80) { + root.yRot = Mth.lerp(Mth.frac(ageInTicks), entity.prevSpin, entity.spin) * Mth.DEG_TO_RAD; + } + } + + @Override + public ModelPart root() { + return root; + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/entity/TinyCreteorModel.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/entity/TinyCreteorModel.java new file mode 100644 index 00000000..72af3fac --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/model/entity/TinyCreteorModel.java @@ -0,0 +1,58 @@ +package cn.leolezury.eternalstarlight.common.client.model.entity; + +import cn.leolezury.eternalstarlight.common.EternalStarlight; +import cn.leolezury.eternalstarlight.common.client.model.animation.AnimatedEntityModel; +import cn.leolezury.eternalstarlight.common.entity.living.monster.TinyCreteor; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.model.geom.ModelLayerLocation; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.*; +import net.minecraft.util.Mth; + +@Environment(EnvType.CLIENT) +public class TinyCreteorModel extends AnimatedEntityModel { + public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(EternalStarlight.id("tiny_creteor"), "main"); + public static final ModelLayerLocation ARMOR_LOCATION = new ModelLayerLocation(EternalStarlight.id("tiny_creteor"), "armor"); + private final ModelPart root; + private final ModelPart rotator; + + public TinyCreteorModel(ModelPart root) { + this.root = root.getChild("root"); + this.rotator = root.getChild("root").getChild("rotator"); + } + + public static LayerDefinition createBodyLayer(CubeDeformation deformation) { + MeshDefinition meshdefinition = new MeshDefinition(); + PartDefinition partdefinition = meshdefinition.getRoot(); + + PartDefinition root = partdefinition.addOrReplaceChild("root", CubeListBuilder.create(), PartPose.offset(0.0F, 20.0F, 0.0F)); + + PartDefinition rotator = root.addOrReplaceChild("rotator", CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -4.0F, -4.0F, 8.0F, 8.0F, 8.0F, deformation), PartPose.offset(0.0F, 0.0F, 0.0F)); + + rotator.addOrReplaceChild("crystal1", CubeListBuilder.create().texOffs(33, 8).addBox(-4.0F, -4.0F, 0.0F, 6.0F, 6.0F, 0.0F, deformation), PartPose.offset(-4.0F, -4.0F, 0.5F)); + + rotator.addOrReplaceChild("crystal2", CubeListBuilder.create().texOffs(1, 26).addBox(-2.5F, -6.0F, 0.0F, 5.0F, 6.0F, 0.0F, deformation), PartPose.offsetAndRotation(-4.0F, 1.5F, 0.0F, 0.0F, 0.0F, -1.5708F)); + + rotator.addOrReplaceChild("crystal3", CubeListBuilder.create().texOffs(1, 26).mirror().addBox(-2.5F, -6.0F, 0.0F, 5.0F, 6.0F, 0.0F, deformation).mirror(false), PartPose.offsetAndRotation(0.0F, 4.0F, 0.0F, 0.0F, 0.0F, -3.1416F)); + + rotator.addOrReplaceChild("crystal4", CubeListBuilder.create().texOffs(1, 17).mirror().addBox(0.0F, -8.0F, 0.0F, 4.0F, 8.0F, 0.0F, deformation).mirror(false), PartPose.offsetAndRotation(0.0F, -4.0F, 0.0F, 0.0F, 0.0F, 0.3927F)); + + rotator.addOrReplaceChild("crystal5", CubeListBuilder.create().texOffs(33, 15).addBox(0.0F, -2.5F, 0.0F, 5.0F, 5.0F, 0.0F, deformation), PartPose.offset(4.0F, 0.5F, 0.0F)); + + return LayerDefinition.create(meshdefinition, 64, 32); + } + + @Override + public void setupAnim(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + rotator.zRot = -Mth.rotLerp(Mth.frac(ageInTicks), entity.prevRollAngle, entity.rollAngle) * Mth.DEG_TO_RAD; + root.xRot = headPitch * Mth.DEG_TO_RAD; + root.yRot = netHeadYaw * Mth.DEG_TO_RAD; + } + + @Override + public ModelPart root() { + return root; + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/particle/effect/ExplosionShockParticle.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/particle/effect/ExplosionShockParticle.java new file mode 100644 index 00000000..112ccc2e --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/particle/effect/ExplosionShockParticle.java @@ -0,0 +1,77 @@ +package cn.leolezury.eternalstarlight.common.client.particle.effect; + +import cn.leolezury.eternalstarlight.common.client.handler.ClientHandlers; +import cn.leolezury.eternalstarlight.common.particle.ExplosionShockParticleOptions; +import cn.leolezury.eternalstarlight.common.util.Easing; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.Camera; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; +import org.joml.Vector3f; + +@Environment(EnvType.CLIENT) +public class ExplosionShockParticle extends TextureSheetParticle { + private final Vec3 direction; + private final float length; + private final Vector3f fromColor, toColor; + + protected ExplosionShockParticle(ClientLevel clientLevel, double x, double y, double z, double dx, double dy, double dz, Vector3f fromColor, Vector3f toColor, SpriteSet spriteSet) { + super(clientLevel, x, y, z, dx, dy, dz); + this.friction = 0; + this.lifetime = (int) (this.random.nextFloat() * 7 + 7); + this.direction = new Vec3(dx, dy, dz).normalize(); + this.length = this.random.nextFloat() * 1.25f + 1.15f; + this.fromColor = fromColor; + this.toColor = toColor; + this.pickSprite(spriteSet); + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_OPAQUE; + } + + @Override + public void render(VertexConsumer consumer, Camera camera, float partialTick) { + Vec3 camPos = camera.getPosition(); + PoseStack stack = new PoseStack(); + stack.pushPose(); + stack.translate(-camPos.x, -camPos.y, -camPos.z); + double currentX = Mth.lerp(partialTick, this.xo, this.x); + double currentY = Mth.lerp(partialTick, this.yo, this.y); + double currentZ = Mth.lerp(partialTick, this.zo, this.z); + Vec3 sight = camPos.subtract(currentX, currentY, currentZ).scale(-1); + Vec3 start = new Vec3(currentX, currentY, currentZ).add(direction.scale(Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, 0, length * 2f))); + Vec3 end = start.add(direction.scale(Easing.IN_OUT_QUAD.interpolate(Mth.abs(Math.min(age + partialTick, lifetime) / lifetime - 0.5f) * 2, length / 2f, 0))); + Vec3 offset = end.subtract(start); + Vec3 sideOffset = offset.cross(sight).normalize().scale(0.03); + PoseStack.Pose pose = stack.last(); + float u0 = this.getU0(); + float u1 = Easing.IN_OUT_QUAD.interpolate(Mth.abs(Math.min(age + partialTick, lifetime) / lifetime - 0.5f) * 2, this.getU1(), this.getU0()); + float v0 = this.getV0(); + float v1 = this.getV1(); + consumer.addVertex(pose, start.add(sideOffset).toVector3f()).setColor(Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.x(), toColor.x()) / 255, Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.y(), toColor.y()) / 255, Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.z(), toColor.z()) / 255, 1).setUv(u0, v0).setLight(ClientHandlers.FULL_BRIGHT); + consumer.addVertex(pose, start.add(sideOffset.scale(-1)).toVector3f()).setColor(Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.x(), toColor.x()) / 255, Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.y(), toColor.y()) / 255, Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.z(), toColor.z()) / 255, 1).setUv(u0, v1).setLight(ClientHandlers.FULL_BRIGHT); + consumer.addVertex(pose, end.add(sideOffset.scale(-1)).toVector3f()).setColor(Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.x(), toColor.x()) / 255, Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.y(), toColor.y()) / 255, Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.z(), toColor.z()) / 255, 1).setUv(u1, v1).setLight(ClientHandlers.FULL_BRIGHT); + consumer.addVertex(pose, end.add(sideOffset).toVector3f()).setColor(Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.x(), toColor.x()) / 255, Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.y(), toColor.y()) / 255, Easing.IN_OUT_QUAD.interpolate(Math.min(age + partialTick, lifetime) / lifetime, fromColor.z(), toColor.z()) / 255, 1).setUv(u1, v0).setLight(ClientHandlers.FULL_BRIGHT); + stack.popPose(); + } + + public static class Provider implements ParticleProvider { + private final SpriteSet sprites; + + public Provider(SpriteSet spriteSet) { + this.sprites = spriteSet; + } + + @Override + public Particle createParticle(ExplosionShockParticleOptions options, ClientLevel level, double x, double y, double z, double dx, double dy, double dz) { + return new ExplosionShockParticle(level, x, y, z, dx, dy, dz, options.fromColor(), options.toColor(), sprites); + } + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/entity/CreteorRenderer.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/entity/CreteorRenderer.java new file mode 100644 index 00000000..978ee79a --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/entity/CreteorRenderer.java @@ -0,0 +1,46 @@ +package cn.leolezury.eternalstarlight.common.client.renderer.entity; + +import cn.leolezury.eternalstarlight.common.EternalStarlight; +import cn.leolezury.eternalstarlight.common.client.model.entity.CreteorModel; +import cn.leolezury.eternalstarlight.common.client.renderer.layer.CreteorPowerLayer; +import cn.leolezury.eternalstarlight.common.entity.living.monster.Creteor; +import com.mojang.blaze3d.vertex.PoseStack; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +@Environment(EnvType.CLIENT) +public class CreteorRenderer extends MobRenderer> { + private static final ResourceLocation ENTITY_TEXTURE = EternalStarlight.id("textures/entity/creteor.png"); + + public CreteorRenderer(EntityRendererProvider.Context context) { + super(context, new CreteorModel<>(context.bakeLayer(CreteorModel.LAYER_LOCATION)), 0.5f); + this.addLayer(new CreteorPowerLayer<>(this, context.getModelSet())); + } + + @Override + protected void scale(T entity, PoseStack poseStack, float f) { + float swell = entity.getSwellProgress(f); + float factor = 1.0F + Mth.sin(swell * 600.0F) * swell * 0.1F; + swell = Mth.clamp(swell, 0.0F, 1.0F); + swell *= swell; + swell *= swell; + float xz = (1.0F + swell * 0.4F) * factor; + float y = (1.0F + swell * 0.1F) / factor; + poseStack.scale(xz, y, xz); + } + + @Override + protected float getWhiteOverlayProgress(T entity, float f) { + float swell = entity.getSwellProgress(f); + return (int) (swell * 45.0F) % 2 == 0 ? 0.0F : Mth.clamp(swell, 0.2F, 1.0F); + } + + @Override + public ResourceLocation getTextureLocation(T entity) { + return ENTITY_TEXTURE; + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/entity/TinyCreteorRenderer.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/entity/TinyCreteorRenderer.java new file mode 100644 index 00000000..d1575e2c --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/entity/TinyCreteorRenderer.java @@ -0,0 +1,46 @@ +package cn.leolezury.eternalstarlight.common.client.renderer.entity; + +import cn.leolezury.eternalstarlight.common.EternalStarlight; +import cn.leolezury.eternalstarlight.common.client.model.entity.TinyCreteorModel; +import cn.leolezury.eternalstarlight.common.client.renderer.layer.TinyCreteorPowerLayer; +import cn.leolezury.eternalstarlight.common.entity.living.monster.TinyCreteor; +import com.mojang.blaze3d.vertex.PoseStack; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.MobRenderer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +@Environment(EnvType.CLIENT) +public class TinyCreteorRenderer extends MobRenderer> { + private static final ResourceLocation ENTITY_TEXTURE = EternalStarlight.id("textures/entity/tiny_creteor.png"); + + public TinyCreteorRenderer(EntityRendererProvider.Context context) { + super(context, new TinyCreteorModel<>(context.bakeLayer(TinyCreteorModel.LAYER_LOCATION)), 0.5f); + this.addLayer(new TinyCreteorPowerLayer<>(this, context.getModelSet())); + } + + @Override + protected void scale(T entity, PoseStack poseStack, float f) { + float swell = entity.getSwellProgress(f); + float factor = 1.0F + Mth.sin(swell * 200.0F) * swell * 0.05F; + swell = Mth.clamp(swell, 0.0F, 1.0F); + swell *= swell; + swell *= swell; + float xz = (1.0F + swell * 0.4F) * factor; + float y = (1.0F + swell * 0.1F) / factor; + poseStack.scale(xz, y, xz); + } + + @Override + protected float getWhiteOverlayProgress(T entity, float f) { + float swell = entity.getSwellProgress(f); + return (int) (swell * 40.0F) % 2 == 0 ? 0.0F : Mth.clamp(swell, 0.05F, 1.0F); + } + + @Override + public ResourceLocation getTextureLocation(T entity) { + return ENTITY_TEXTURE; + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/layer/CreteorPowerLayer.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/layer/CreteorPowerLayer.java new file mode 100644 index 00000000..833c7fc8 --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/layer/CreteorPowerLayer.java @@ -0,0 +1,37 @@ +package cn.leolezury.eternalstarlight.common.client.renderer.layer; + +import cn.leolezury.eternalstarlight.common.client.model.entity.CreteorModel; +import cn.leolezury.eternalstarlight.common.entity.living.monster.Creteor; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.EnergySwirlLayer; +import net.minecraft.resources.ResourceLocation; + +@Environment(EnvType.CLIENT) +public class CreteorPowerLayer extends EnergySwirlLayer> { + private static final ResourceLocation POWER_LOCATION = ResourceLocation.withDefaultNamespace("textures/entity/creeper/creeper_armor.png"); + private final CreteorModel model; + + public CreteorPowerLayer(RenderLayerParent> parent, EntityModelSet modelSet) { + super(parent); + this.model = new CreteorModel<>(modelSet.bakeLayer(CreteorModel.ARMOR_LOCATION)); + } + + @Override + protected float xOffset(float f) { + return f * 0.01F; + } + + @Override + protected ResourceLocation getTextureLocation() { + return POWER_LOCATION; + } + + @Override + protected EntityModel model() { + return this.model; + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/layer/TinyCreteorPowerLayer.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/layer/TinyCreteorPowerLayer.java new file mode 100644 index 00000000..17ae1e8e --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/client/renderer/layer/TinyCreteorPowerLayer.java @@ -0,0 +1,37 @@ +package cn.leolezury.eternalstarlight.common.client.renderer.layer; + +import cn.leolezury.eternalstarlight.common.client.model.entity.TinyCreteorModel; +import cn.leolezury.eternalstarlight.common.entity.living.monster.TinyCreteor; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.geom.EntityModelSet; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.EnergySwirlLayer; +import net.minecraft.resources.ResourceLocation; + +@Environment(EnvType.CLIENT) +public class TinyCreteorPowerLayer extends EnergySwirlLayer> { + private static final ResourceLocation POWER_LOCATION = ResourceLocation.withDefaultNamespace("textures/entity/creeper/creeper_armor.png"); + private final TinyCreteorModel model; + + public TinyCreteorPowerLayer(RenderLayerParent> parent, EntityModelSet modelSet) { + super(parent); + this.model = new TinyCreteorModel<>(modelSet.bakeLayer(TinyCreteorModel.ARMOR_LOCATION)); + } + + @Override + protected float xOffset(float f) { + return f * 0.01F; + } + + @Override + protected ResourceLocation getTextureLocation() { + return POWER_LOCATION; + } + + @Override + protected EntityModel model() { + return this.model; + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/config/ESConfig.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/config/ESConfig.java index 09e49b3b..bfe471f2 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/config/ESConfig.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/config/ESConfig.java @@ -28,6 +28,8 @@ public static class MobsConfig { public final AttackingMobConfig lonestarSkeleton = new AttackingMobConfig(20, 0, 3.2, 16, true); public final AttackingMobConfig nightfallSpider = new AttackingMobConfig(10, 0, 2, 16, true); public final AttackingMobConfig thirstWalker = new AttackingMobConfig(40, 0, 4.5, 32, true); + public final AttackingMobConfig creteor = new AttackingMobConfig(15, 0, 5, 48, true); + public final AttackingMobConfig tinyCreteor = new AttackingMobConfig(5, 0, 2, 48, true); public final MobConfig ent = new MobConfig(10, 0, true); public final MobConfig ratlin = new MobConfig(15, 0, true); public final MobConfig yeti = new MobConfig(20, 0, true); diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/animal/Yeti.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/animal/Yeti.java index 5a375986..40daca55 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/animal/Yeti.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/animal/Yeti.java @@ -14,6 +14,7 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -148,7 +149,7 @@ public void aiStep() { idleAnimationState.startIfStopped(tickCount); prevRollAngle = rollAngle; rollAngle += (float) (position().subtract(new Vec3(xOld, yOld, zOld)).length() / (3f / 260f)); - rollAngle = rollAngle % 360; + rollAngle = Mth.wrapDegrees(rollAngle); } } diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/goal/MoveToTargetGoal.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/goal/MoveToTargetGoal.java new file mode 100644 index 00000000..ecb6bdd1 --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/goal/MoveToTargetGoal.java @@ -0,0 +1,50 @@ +package cn.leolezury.eternalstarlight.common.entity.living.goal; + +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.phys.Vec3; + +import java.util.EnumSet; + +public class MoveToTargetGoal extends Goal { + private final Mob mob; + private final double speedModifier; + private final int recalculateInterval; + private Vec3 lastTargetPos = Vec3.ZERO; + private int lastRecalculate = 0; + + public MoveToTargetGoal(Mob mob, double speedModifier) { + this(mob, speedModifier, 60); + } + + public MoveToTargetGoal(Mob mob, double speedModifier, int recalculateInterval) { + setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK)); + this.mob = mob; + this.speedModifier = speedModifier; + this.recalculateInterval = recalculateInterval; + } + + @Override + public boolean requiresUpdateEveryTick() { + return true; + } + + public boolean canUse() { + return mob.getTarget() != null; + } + + public boolean canContinueToUse() { + return mob.getTarget() != null; + } + + public void tick() { + if (mob.getTarget() != null) { + mob.getLookControl().setLookAt(mob.getTarget(), 360, 360); + if (lastTargetPos != mob.getTarget().position() && mob.tickCount - lastRecalculate > recalculateInterval) { + lastTargetPos = mob.getTarget().position(); + lastRecalculate = mob.tickCount; + mob.getNavigation().moveTo(mob.getTarget().getX(), mob.getTarget().getY(), mob.getTarget().getZ(), speedModifier); + } + } + } +} \ No newline at end of file diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/Creteor.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/Creteor.java new file mode 100644 index 00000000..cca82349 --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/Creteor.java @@ -0,0 +1,339 @@ +package cn.leolezury.eternalstarlight.common.entity.living.monster; + +import cn.leolezury.eternalstarlight.common.config.ESConfig; +import cn.leolezury.eternalstarlight.common.network.ParticlePacket; +import cn.leolezury.eternalstarlight.common.particle.ExplosionShockParticleOptions; +import cn.leolezury.eternalstarlight.common.platform.ESPlatform; +import cn.leolezury.eternalstarlight.common.registry.ESEntities; +import cn.leolezury.eternalstarlight.common.registry.ESSoundEvents; +import net.minecraft.core.BlockPos; +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.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.tags.ItemTags; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.goal.MeleeAttackGoal; +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +import java.util.Collection; +import java.util.EnumSet; + +public class Creteor extends Monster implements PowerableMob { + private static final String TAG_ACTIVATED = "activated"; + private static final String TAG_IGNITED = "ignited"; + private static final String TAG_POWERED = "powered"; + private static final String TAG_SWELL = "swell"; + private static final String TAG_SPIN_TICKS = "spin_ticks"; + + public AnimationState idleAnimationState = new AnimationState(); + + protected static final EntityDataAccessor ACTIVATED = SynchedEntityData.defineId(Creteor.class, EntityDataSerializers.BOOLEAN); + + public boolean isActivated() { + return this.getEntityData().get(ACTIVATED); + } + + public void setActivated(boolean activated) { + this.getEntityData().set(ACTIVATED, activated); + } + + protected static final EntityDataAccessor IGNITED = SynchedEntityData.defineId(Creteor.class, EntityDataSerializers.BOOLEAN); + + public boolean isIgnited() { + return this.getEntityData().get(IGNITED); + } + + public void setIgnited(boolean ignited) { + this.getEntityData().set(IGNITED, ignited); + } + + protected static final EntityDataAccessor POWERED = SynchedEntityData.defineId(Creteor.class, EntityDataSerializers.BOOLEAN); + + @Override + public boolean isPowered() { + return this.getEntityData().get(POWERED); + } + + public void setPowered(boolean powered) { + this.getEntityData().set(POWERED, powered); + } + + protected static final EntityDataAccessor SWELL = SynchedEntityData.defineId(Creteor.class, EntityDataSerializers.INT); + + public int getSwell() { + return this.getEntityData().get(SWELL); + } + + public void setSwell(int swell) { + this.getEntityData().set(SWELL, swell); + } + + public int oldSwell; + public int spinTicks; + public float rollAngle, prevRollAngle; + public float spin, prevSpin; + + public Creteor(EntityType type, Level level) { + super(type, level); + } + + @Override + protected void defineSynchedData(SynchedEntityData.Builder builder) { + super.defineSynchedData(builder); + builder.define(ACTIVATED, false) + .define(IGNITED, false) + .define(POWERED, false) + .define(SWELL, 0); + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new CreteorDoNothingGoal()); + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0, false)); + this.goalSelector.addGoal(3, new WaterAvoidingRandomStrollGoal(this, 1.0, 0.0F)); + this.targetSelector.addGoal(0, new HurtByTargetGoal(this).setAlertOthers()); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true) { + @Override + public boolean canUse() { + return super.canUse() && Creteor.this.isActivated(); + } + }); + } + + class CreteorDoNothingGoal extends Goal { + public CreteorDoNothingGoal() { + this.setFlags(EnumSet.of(Flag.MOVE, Flag.JUMP, Flag.LOOK)); + } + + public boolean canUse() { + return !Creteor.this.isActivated(); + } + } + + public static AttributeSupplier.Builder createAttributes() { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, ESConfig.INSTANCE.mobsConfig.creteor.maxHealth()) + .add(Attributes.ARMOR, ESConfig.INSTANCE.mobsConfig.creteor.armor()) + .add(Attributes.ATTACK_DAMAGE, ESConfig.INSTANCE.mobsConfig.creteor.attackDamage()) + .add(Attributes.FOLLOW_RANGE, ESConfig.INSTANCE.mobsConfig.creteor.followRange()) + .add(Attributes.MOVEMENT_SPEED, 0.3); + } + + @Override + public void aiStep() { + super.aiStep(); + oldSwell = getSwell(); + if (getSwell() < 80) { + spinTicks = 0; + } else { + spinTicks++; + } + if (!level().isClientSide) { + if ((getTarget() != null || isIgnited()) && !isActivated()) { + setActivated(true); + } + if (getSwell() < 80) { + LivingEntity target = getTarget(); + if (isIgnited()) { + setSwell(getSwell() + 1); + } else if (target == null) { + setSwell(getSwell() - 1); + } else if (distanceToSqr(target) > (double) 25.0F) { + setSwell(getSwell() - 1); + } else if (!getSensing().hasLineOfSight(target)) { + setSwell(getSwell() - 1); + } else { + setSwell(getSwell() + 1); + } + setSwell(Mth.clamp(getSwell(), 0, 80)); + } else { + setNoGravity(true); + hurtMarked = true; + if (spinTicks <= 40) { + setDeltaMovement(new Vec3(0, 0.1, 0)); + } else { + setDeltaMovement(Vec3.ZERO); + } + if (spinTicks == 1) { + playSound(ESSoundEvents.CRETEOR_CHARGE.get()); + } + if (spinTicks > 80) { + explode(); + } + } + } else { + idleAnimationState.startIfStopped(tickCount); + prevRollAngle = rollAngle; + rollAngle += (float) (position().subtract(new Vec3(xOld, yOld, zOld)).length() / (3f / 260f)); + rollAngle = Mth.wrapDegrees(rollAngle); + if (!isActivated()) { + rollAngle = 0; + } + prevSpin = spin; + if (getSwell() >= 80) { + spin += 90; + } + } + } + + @Override + public void setDeltaMovement(Vec3 vec3) { + super.setDeltaMovement(isActivated() ? vec3 : new Vec3(0, vec3.y, 0)); + } + + public float getSwellProgress(float partialTick) { + if (getSwell() < 80) { + return Mth.lerp(partialTick, oldSwell, getSwell()) / 160f; + } else { + return Math.min(spinTicks + 80 + partialTick, 160) / 160f; + } + } + + @Override + public void thunderHit(ServerLevel serverLevel, LightningBolt lightningBolt) { + super.thunderHit(serverLevel, lightningBolt); + setPowered(true); + } + + @Override + public boolean hurt(DamageSource source, float amount) { + if (!isActivated()) { + setActivated(true); + } + return super.hurt(source, amount); + } + + @Override + protected InteractionResult mobInteract(Player player, InteractionHand interactionHand) { + ItemStack itemStack = player.getItemInHand(interactionHand); + if (itemStack.is(ItemTags.CREEPER_IGNITERS)) { + SoundEvent soundEvent = itemStack.is(Items.FIRE_CHARGE) ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; + this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundEvent, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); + if (!this.level().isClientSide) { + setIgnited(true); + if (!itemStack.isDamageableItem()) { + itemStack.shrink(1); + } else { + itemStack.hurtAndBreak(1, player, getSlotForHand(interactionHand)); + } + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { + return super.mobInteract(player, interactionHand); + } + } + + private void explode() { + if (!this.level().isClientSide) { + float f = this.isPowered() ? 2.0F : 1.0F; + this.dead = true; + this.level().explode(this, this.getX(), this.getY(), this.getZ(), 3 * f, Level.ExplosionInteraction.MOB); + if (level() instanceof ServerLevel serverLevel) { + for (int i = 0; i < 25; i++) { + Vec3 speed = new Vec3((this.random.nextFloat() - this.random.nextFloat()) * 0.1F, this.random.nextFloat() * 0.05F, (this.random.nextFloat() - this.random.nextFloat()) * 0.1F).normalize(); + ESPlatform.INSTANCE.sendToAllClients(serverLevel, new ParticlePacket(ExplosionShockParticleOptions.AETHERSENT, getEyePosition().x + speed.x * 1.2, getEyePosition().y + speed.y * 1.2, getEyePosition().z + speed.z * 1.2, speed.x, speed.y, speed.z)); + } + } + playSound(ESSoundEvents.CRETEOR_EXPLODE.get()); + this.spawnLingeringCloud(); + this.triggerOnDeathMobEffects(RemovalReason.KILLED); + this.discard(); + if (ESConfig.INSTANCE.mobsConfig.tinyCreteor.canSpawn()) { + int splitCount = getRandom().nextInt(2, 5); + for (int i = 0; i < splitCount; i++) { + TinyCreteor tinyCreteor = new TinyCreteor(ESEntities.TINY_CRETEOR.get(), level()); + tinyCreteor.setPos(position().add(0, getBbHeight() / 2, 0)); + tinyCreteor.setPowered(isPowered()); + tinyCreteor.setTarget(getTarget()); + level().addFreshEntity(tinyCreteor); + tinyCreteor.hurtMarked = true; + tinyCreteor.setDeltaMovement(new Vec3((getRandom().nextFloat() - getRandom().nextFloat()) * 0.1F, getRandom().nextFloat() * 0.05F, (getRandom().nextFloat() - getRandom().nextFloat()) * 0.1F)); + } + } + } + } + + private void spawnLingeringCloud() { + Collection collection = this.getActiveEffects(); + if (!collection.isEmpty()) { + AreaEffectCloud areaEffectCloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + areaEffectCloud.setRadius(2.5F); + areaEffectCloud.setRadiusOnUse(-0.5F); + areaEffectCloud.setWaitTime(10); + areaEffectCloud.setDuration(areaEffectCloud.getDuration() / 2); + areaEffectCloud.setRadiusPerTick(-areaEffectCloud.getRadius() / (float) areaEffectCloud.getDuration()); + + for (MobEffectInstance mobEffectInstance : collection) { + areaEffectCloud.addEffect(new MobEffectInstance(mobEffectInstance)); + } + + this.level().addFreshEntity(areaEffectCloud); + } + } + + @Override + protected void playStepSound(BlockPos blockPos, BlockState blockState) { + super.playStepSound(blockPos, blockState); + playSound(ESSoundEvents.CRETEOR_ROLL.get()); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damageSource) { + return ESSoundEvents.CRETEOR_HURT.get(); + } + + @Override + protected SoundEvent getDeathSound() { + return ESSoundEvents.CRETEOR_DEATH.get(); + } + + @Override + public void addAdditionalSaveData(CompoundTag compoundTag) { + super.addAdditionalSaveData(compoundTag); + compoundTag.putBoolean(TAG_ACTIVATED, isActivated()); + compoundTag.putBoolean(TAG_IGNITED, isIgnited()); + compoundTag.putBoolean(TAG_POWERED, isPowered()); + compoundTag.putInt(TAG_SWELL, getSwell()); + compoundTag.putInt(TAG_SPIN_TICKS, spinTicks); + } + + @Override + public void readAdditionalSaveData(CompoundTag compoundTag) { + super.readAdditionalSaveData(compoundTag); + setActivated(compoundTag.getBoolean(TAG_ACTIVATED)); + setIgnited(compoundTag.getBoolean(TAG_IGNITED)); + setPowered(compoundTag.getBoolean(TAG_POWERED)); + setSwell(compoundTag.getInt(TAG_SWELL)); + spinTicks = compoundTag.getInt(TAG_SPIN_TICKS); + } + + public static boolean checkCreteorSpawnRules(EntityType type, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { + return checkAnyLightMonsterSpawnRules(type, level, spawnType, pos, random) && ESConfig.INSTANCE.mobsConfig.creteor.canSpawn(); + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/TangledSkull.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/TangledSkull.java index 35673892..ac205d7e 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/TangledSkull.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/TangledSkull.java @@ -362,11 +362,11 @@ public void tick() { TangledSkull.this.setDeltaMovement(TangledSkull.this.getDeltaMovement().add(vec3.scale(this.speedModifier * 0.05 / d))); if (TangledSkull.this.getTarget() == null) { Vec3 vec32 = TangledSkull.this.getDeltaMovement(); - TangledSkull.this.setYRot(-((float) Mth.atan2(vec32.x, vec32.z)) * 57.295776F); + TangledSkull.this.setYRot(-((float) Mth.atan2(vec32.x, vec32.z)) * Mth.RAD_TO_DEG); } else { double e = TangledSkull.this.getTarget().getX() - TangledSkull.this.getX(); double f = TangledSkull.this.getTarget().getZ() - TangledSkull.this.getZ(); - TangledSkull.this.setYRot(-((float) Mth.atan2(e, f)) * 57.295776F); + TangledSkull.this.setYRot(-((float) Mth.atan2(e, f)) * Mth.RAD_TO_DEG); } TangledSkull.this.yBodyRot = TangledSkull.this.getYRot(); } diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/TinyCreteor.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/TinyCreteor.java new file mode 100644 index 00000000..e9c5c6a1 --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/entity/living/monster/TinyCreteor.java @@ -0,0 +1,260 @@ +package cn.leolezury.eternalstarlight.common.entity.living.monster; + +import cn.leolezury.eternalstarlight.common.config.ESConfig; +import cn.leolezury.eternalstarlight.common.entity.living.goal.MoveToTargetGoal; +import cn.leolezury.eternalstarlight.common.entity.living.goal.RandomFlyGoal; +import cn.leolezury.eternalstarlight.common.network.ParticlePacket; +import cn.leolezury.eternalstarlight.common.particle.ExplosionShockParticleOptions; +import cn.leolezury.eternalstarlight.common.platform.ESPlatform; +import cn.leolezury.eternalstarlight.common.registry.ESSoundEvents; +import net.minecraft.core.BlockPos; +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.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.tags.ItemTags; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.FlyingMoveControl; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal; +import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal; +import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; +import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +import java.util.Collection; + +public class TinyCreteor extends Monster implements PowerableMob { + private static final String TAG_IGNITED = "ignited"; + private static final String TAG_POWERED = "powered"; + private static final String TAG_SWELL = "swell"; + + protected static final EntityDataAccessor IGNITED = SynchedEntityData.defineId(TinyCreteor.class, EntityDataSerializers.BOOLEAN); + + public boolean isIgnited() { + return this.getEntityData().get(IGNITED); + } + + public void setIgnited(boolean ignited) { + this.getEntityData().set(IGNITED, ignited); + } + + protected static final EntityDataAccessor POWERED = SynchedEntityData.defineId(TinyCreteor.class, EntityDataSerializers.BOOLEAN); + + @Override + public boolean isPowered() { + return this.getEntityData().get(POWERED); + } + + public void setPowered(boolean powered) { + this.getEntityData().set(POWERED, powered); + } + + protected static final EntityDataAccessor SWELL = SynchedEntityData.defineId(TinyCreteor.class, EntityDataSerializers.INT); + + public int getSwell() { + return this.getEntityData().get(SWELL); + } + + public void setSwell(int swell) { + this.getEntityData().set(SWELL, swell); + } + + public int oldSwell; + public float rollAngle, prevRollAngle; + + public TinyCreteor(EntityType entityType, Level level) { + super(entityType, level); + this.moveControl = new FlyingMoveControl(this, 20, true); + this.setNoGravity(true); + } + + @Override + protected void defineSynchedData(SynchedEntityData.Builder builder) { + super.defineSynchedData(builder); + builder.define(IGNITED, false) + .define(POWERED, false) + .define(SWELL, 0); + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new MoveToTargetGoal(this, 1.0D)); + this.goalSelector.addGoal(2, new RandomFlyGoal(this)); + this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(4, new LookAtPlayerGoal(this, Mob.class, 8.0F)); + this.targetSelector.addGoal(0, new HurtByTargetGoal(this).setAlertOthers()); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } + + public static AttributeSupplier.Builder createAttributes() { + return Monster.createMonsterAttributes() + .add(Attributes.MAX_HEALTH, ESConfig.INSTANCE.mobsConfig.tinyCreteor.maxHealth()) + .add(Attributes.ARMOR, ESConfig.INSTANCE.mobsConfig.tinyCreteor.armor()) + .add(Attributes.ATTACK_DAMAGE, ESConfig.INSTANCE.mobsConfig.tinyCreteor.attackDamage()) + .add(Attributes.FOLLOW_RANGE, ESConfig.INSTANCE.mobsConfig.tinyCreteor.followRange()) + .add(Attributes.MOVEMENT_SPEED, 0D) + .add(Attributes.FLYING_SPEED, 1D); + } + + @Override + protected PathNavigation createNavigation(Level level) { + FlyingPathNavigation navigation = new FlyingPathNavigation(this, level) { + @Override + public boolean isStableDestination(BlockPos blockPos) { + return this.level.getBlockState(blockPos).isAir(); + } + }; + navigation.setCanOpenDoors(true); + navigation.setCanFloat(true); + navigation.setCanPassDoors(true); + return navigation; + } + + @Override + public void aiStep() { + super.aiStep(); + oldSwell = getSwell(); + if (!level().isClientSide) { + if (getSwell() < 80) { + LivingEntity target = getTarget(); + if (isIgnited()) { + setSwell(getSwell() + 1); + } else if (target == null) { + setSwell(getSwell() - 1); + } else if (distanceToSqr(target) > (double) 25.0F) { + setSwell(getSwell() - 1); + } else if (!getSensing().hasLineOfSight(target)) { + setSwell(getSwell() - 1); + } else { + setSwell(getSwell() + 1); + } + setSwell(Mth.clamp(getSwell(), 0, 80)); + } else { + explode(); + } + BlockHitResult result = level().clip(new ClipContext(position(), position().subtract(0, 2, 0), ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)); + if (onGround() || (result.getType() != HitResult.Type.MISS && result.getLocation().distanceTo(position()) < 0.5)) { + addDeltaMovement(new Vec3(0, 0.01, 0)); + } + } else { + prevRollAngle = rollAngle; + rollAngle += (getSwell() / 80f) * 30; + if (getSwell() == 0) { + rollAngle = Mth.approachDegrees(rollAngle, 0, 15); + } + } + } + + public float getSwellProgress(float partialTick) { + return Mth.lerp(partialTick, oldSwell, getSwell()) / 80f; + } + + @Override + public void thunderHit(ServerLevel serverLevel, LightningBolt lightningBolt) { + super.thunderHit(serverLevel, lightningBolt); + setPowered(true); + } + + @Override + protected InteractionResult mobInteract(Player player, InteractionHand interactionHand) { + ItemStack itemStack = player.getItemInHand(interactionHand); + if (itemStack.is(ItemTags.CREEPER_IGNITERS)) { + SoundEvent soundEvent = itemStack.is(Items.FIRE_CHARGE) ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; + this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundEvent, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); + if (!this.level().isClientSide) { + setIgnited(true); + if (!itemStack.isDamageableItem()) { + itemStack.shrink(1); + } else { + itemStack.hurtAndBreak(1, player, getSlotForHand(interactionHand)); + } + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { + return super.mobInteract(player, interactionHand); + } + } + + private void explode() { + if (!this.level().isClientSide) { + this.dead = true; + this.level().explode(this, this.getX(), this.getY(), this.getZ(), this.isPowered() ? 3.0F : 2.0F, Level.ExplosionInteraction.MOB); + if (level() instanceof ServerLevel serverLevel) { + for (int i = 0; i < 12; i++) { + Vec3 speed = new Vec3((this.random.nextFloat() - this.random.nextFloat()) * 0.1F, this.random.nextFloat() * 0.05F, (this.random.nextFloat() - this.random.nextFloat()) * 0.1F).normalize(); + ESPlatform.INSTANCE.sendToAllClients(serverLevel, new ParticlePacket(ExplosionShockParticleOptions.AETHERSENT, getEyePosition().x + speed.x * 1.2, getEyePosition().y + speed.y * 1.2, getEyePosition().z + speed.z * 1.2, speed.x, speed.y, speed.z)); + } + } + playSound(ESSoundEvents.CRETEOR_EXPLODE.get()); + this.spawnLingeringCloud(); + this.triggerOnDeathMobEffects(RemovalReason.KILLED); + this.discard(); + } + } + + private void spawnLingeringCloud() { + Collection collection = this.getActiveEffects(); + if (!collection.isEmpty()) { + AreaEffectCloud areaEffectCloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + areaEffectCloud.setRadius(2.5F); + areaEffectCloud.setRadiusOnUse(-0.5F); + areaEffectCloud.setWaitTime(10); + areaEffectCloud.setDuration(areaEffectCloud.getDuration() / 2); + areaEffectCloud.setRadiusPerTick(-areaEffectCloud.getRadius() / (float) areaEffectCloud.getDuration()); + + for (MobEffectInstance mobEffectInstance : collection) { + areaEffectCloud.addEffect(new MobEffectInstance(mobEffectInstance)); + } + + this.level().addFreshEntity(areaEffectCloud); + } + } + + @Override + protected SoundEvent getHurtSound(DamageSource damageSource) { + return ESSoundEvents.CRETEOR_HURT.get(); + } + + @Override + protected SoundEvent getDeathSound() { + return ESSoundEvents.CRETEOR_DEATH.get(); + } + + @Override + public void addAdditionalSaveData(CompoundTag compoundTag) { + super.addAdditionalSaveData(compoundTag); + compoundTag.putBoolean(TAG_IGNITED, isIgnited()); + compoundTag.putBoolean(TAG_POWERED, isPowered()); + compoundTag.putInt(TAG_SWELL, getSwell()); + } + + @Override + public void readAdditionalSaveData(CompoundTag compoundTag) { + super.readAdditionalSaveData(compoundTag); + setIgnited(compoundTag.getBoolean(TAG_IGNITED)); + setPowered(compoundTag.getBoolean(TAG_POWERED)); + setSwell(compoundTag.getInt(TAG_SWELL)); + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/handler/CommonSetupHandlers.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/handler/CommonSetupHandlers.java index fa3f6bcc..879b1706 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/handler/CommonSetupHandlers.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/handler/CommonSetupHandlers.java @@ -246,6 +246,8 @@ public static void createAttributes(EntityAttributeRegisterStrategy strategy) { strategy.register(ESEntities.LONESTAR_SKELETON.get(), LonestarSkeleton.createAttributes().build()); strategy.register(ESEntities.NIGHTFALL_SPIDER.get(), NightfallSpider.createNightfallSpider().build()); strategy.register(ESEntities.THIRST_WALKER.get(), ThirstWalker.createAttributes().build()); + strategy.register(ESEntities.CRETEOR.get(), Creteor.createAttributes().build()); + strategy.register(ESEntities.TINY_CRETEOR.get(), TinyCreteor.createAttributes().build()); strategy.register(ESEntities.ENT.get(), Ent.createAttributes().build()); strategy.register(ESEntities.RATLIN.get(), Ratlin.createAttributes().build()); strategy.register(ESEntities.YETI.get(), Yeti.createAttributes().build()); @@ -276,6 +278,7 @@ public static void registerSpawnPlacements(SpawnPlacementRegisterStrategy strate strategy.register(ESEntities.LONESTAR_SKELETON.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, LonestarSkeleton::checkLonestarSkeletonSpawnRules); strategy.register(ESEntities.NIGHTFALL_SPIDER.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, NightfallSpider::checkNightfallSpiderSpawnRules); strategy.register(ESEntities.THIRST_WALKER.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, ThirstWalker::checkThirstWalkerSpawnRules); + strategy.register(ESEntities.CRETEOR.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Creteor::checkCreteorSpawnRules); strategy.register(ESEntities.ENT.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Ent::checkEntSpawnRules); strategy.register(ESEntities.RATLIN.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Ratlin::checkRatlinSpawnRules); strategy.register(ESEntities.YETI.get(), SpawnPlacementTypes.ON_GROUND, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, Yeti::checkYetiSpawnRules); diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/particle/ExplosionShockParticleOptions.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/particle/ExplosionShockParticleOptions.java new file mode 100644 index 00000000..92a114cb --- /dev/null +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/particle/ExplosionShockParticleOptions.java @@ -0,0 +1,28 @@ +package cn.leolezury.eternalstarlight.common.particle; + +import cn.leolezury.eternalstarlight.common.registry.ESParticles; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.util.ExtraCodecs; +import org.joml.Vector3f; + +public record ExplosionShockParticleOptions(Vector3f fromColor, Vector3f toColor) implements ParticleOptions { + public static final ExplosionShockParticleOptions AETHERSENT = new ExplosionShockParticleOptions(new Vector3f(255, 255, 255), new Vector3f(233, 173, 237)); + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((instance) -> instance.group( + ExtraCodecs.VECTOR3F.fieldOf("from_color").forGetter(ExplosionShockParticleOptions::fromColor), + ExtraCodecs.VECTOR3F.fieldOf("to_color").forGetter(ExplosionShockParticleOptions::toColor) + ).apply(instance, ExplosionShockParticleOptions::new)); + + public static final StreamCodec STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC.codec()); + + @Override + public ParticleType getType() { + return ESParticles.EXPLOSION_SHOCK.get(); + } +} diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESEntities.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESEntities.java index b3f11224..4613aa23 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESEntities.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESEntities.java @@ -31,6 +31,7 @@ public class ESEntities { public static final RegistrationProvider> ENTITIES = RegistrationProvider.get(Registries.ENTITY_TYPE, EternalStarlight.ID); + public static final RegistryObject, EntityType> FALLING_BLOCK = ENTITIES.register( "falling_block", () -> EntityType.Builder.of(ESFallingBlock::new, MobCategory.MISC) @@ -199,6 +200,8 @@ public class ESEntities { .clientTrackingRange(8) .build(entityKey("thirst_walker")) ); + public static final RegistryObject, EntityType> CRETEOR = ENTITIES.register("creteor", () -> EntityType.Builder.of(Creteor::new, MobCategory.MONSTER).sized(0.6F, 1.5F).clientTrackingRange(8).build(EternalStarlight.id("creteor").toString())); + public static final RegistryObject, EntityType> TINY_CRETEOR = ENTITIES.register("tiny_creteor", () -> EntityType.Builder.of(TinyCreteor::new, MobCategory.MONSTER).sized(0.5F, 0.5F).clientTrackingRange(8).build(EternalStarlight.id("tiny_creteor").toString())); public static final RegistryObject, EntityType> ENT = ENTITIES.register("ent", () -> EntityType.Builder.of(Ent::new, MobCategory.CREATURE) .sized(0.7F, 0.3F) diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESItems.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESItems.java index 9fcf4ca5..f295630c 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESItems.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESItems.java @@ -48,6 +48,8 @@ private static RegistryObject registerItem(String name, Supplier LONESTAR_SKELETON_SPAWN_EGG = registerItem("lonestar_skeleton_spawn_egg", () -> ESPlatform.INSTANCE.createSpawnEgg(ESEntities.LONESTAR_SKELETON::get, 0xd9d9d9, 0x4f5158, new Item.Properties())); public static final RegistryObject NIGHTFALL_SPIDER_SPAWN_EGG = registerItem("nightfall_spider_spawn_egg", () -> ESPlatform.INSTANCE.createSpawnEgg(ESEntities.NIGHTFALL_SPIDER::get, 0x233e47, 0x879cca, new Item.Properties())); public static final RegistryObject THIRST_WALKER_SPAWN_EGG = registerItem("thirst_walker_spawn_egg", () -> ESPlatform.INSTANCE.createSpawnEgg(ESEntities.THIRST_WALKER::get, 0x352b2f, 0xa4e0f2, new Item.Properties())); + public static final RegistryObject CRETEOR_SPAWN_EGG = registerItem("creteor_spawn_egg", () -> ESPlatform.INSTANCE.createSpawnEgg(ESEntities.CRETEOR::get, 0x53235b, 0xe9aded, new Item.Properties())); + public static final RegistryObject TINY_CRETEOR_SPAWN_EGG = registerItem("tiny_creteor_spawn_egg", () -> ESPlatform.INSTANCE.createSpawnEgg(ESEntities.TINY_CRETEOR::get, 0x53235b, 0xe9aded, new Item.Properties())); public static final RegistryObject ENT_SPAWN_EGG = registerItem("ent_spawn_egg", () -> ESPlatform.INSTANCE.createSpawnEgg(ESEntities.ENT::get, 0x633737, 0x86b8a9, new Item.Properties())); public static final RegistryObject RATLIN_SPAWN_EGG = registerItem("ratlin_spawn_egg", () -> ESPlatform.INSTANCE.createSpawnEgg(ESEntities.RATLIN::get, 0x544e4e, 0xd7959a, new Item.Properties())); public static final RegistryObject YETI_SPAWN_EGG = registerItem("yeti_spawn_egg", () -> ESPlatform.INSTANCE.createSpawnEgg(ESEntities.YETI::get, 0xe8edff, 0xbda1bc, new Item.Properties())); diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESParticles.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESParticles.java index 51e77de0..c2fb4bfd 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESParticles.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESParticles.java @@ -92,6 +92,17 @@ public StreamCodec streamC public static final RegistryObject, SimpleParticleType> SMOKE_TRAIL = PARTICLE_TYPES.register("smoke_trail", () -> new SimpleParticleType(false)); public static final RegistryObject, SimpleParticleType> AETHERSENT_EXPLOSION = PARTICLE_TYPES.register("aethersent_explosion", () -> new SimpleParticleType(false)); public static final RegistryObject, SimpleParticleType> ASHEN_SNOW = PARTICLE_TYPES.register("ashen_snow", () -> new SimpleParticleType(false)); + public static final RegistryObject, ParticleType> EXPLOSION_SHOCK = PARTICLE_TYPES.register("explosion_shock", () -> new ParticleType<>(false) { + @Override + public MapCodec codec() { + return ExplosionShockParticleOptions.CODEC; + } + + @Override + public StreamCodec streamCodec() { + return ExplosionShockParticleOptions.STREAM_CODEC; + } + }); public static final RegistryObject, SimpleParticleType> ADVANCED_GLOW = PARTICLE_TYPES.register("advanced_glow", () -> new SimpleParticleType(false)); public static final RegistryObject, SimpleParticleType> SHINE = PARTICLE_TYPES.register("shine", () -> new SimpleParticleType(false)); diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESSoundEvents.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESSoundEvents.java index f184faed..050d2ae4 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESSoundEvents.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/registry/ESSoundEvents.java @@ -71,6 +71,12 @@ public class ESSoundEvents { public static final RegistryObject THIRST_WALKER_HURT = register("entity.thirst_walker.hurt"); public static final RegistryObject THIRST_WALKER_DEATH = register("entity.thirst_walker.death"); + public static final RegistryObject CRETEOR_ROLL = register("entity.creteor.roll"); + public static final RegistryObject CRETEOR_HURT = register("entity.creteor.hurt"); + public static final RegistryObject CRETEOR_DEATH = register("entity.creteor.death"); + public static final RegistryObject CRETEOR_CHARGE = register("entity.creteor.charge"); + public static final RegistryObject CRETEOR_EXPLODE = register("entity.creteor.explode"); + public static final RegistryObject LUMINOFISH_HURT = register("entity.luminofish.hurt"); public static final RegistryObject LUMINOFISH_DEATH = register("entity.luminofish.death"); public static final RegistryObject LUMINOFISH_FLOP = register("entity.luminofish.flop"); diff --git a/common/src/main/java/cn/leolezury/eternalstarlight/common/weather/MeteorRainWeather.java b/common/src/main/java/cn/leolezury/eternalstarlight/common/weather/MeteorRainWeather.java index 1b4d8407..0c76ea6a 100644 --- a/common/src/main/java/cn/leolezury/eternalstarlight/common/weather/MeteorRainWeather.java +++ b/common/src/main/java/cn/leolezury/eternalstarlight/common/weather/MeteorRainWeather.java @@ -1,7 +1,10 @@ package cn.leolezury.eternalstarlight.common.weather; import cn.leolezury.eternalstarlight.common.client.ClientWeatherState; +import cn.leolezury.eternalstarlight.common.config.ESConfig; +import cn.leolezury.eternalstarlight.common.entity.living.monster.Creteor; import cn.leolezury.eternalstarlight.common.entity.projectile.AethersentMeteor; +import cn.leolezury.eternalstarlight.common.registry.ESEntities; import cn.leolezury.eternalstarlight.common.registry.ESParticles; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -12,7 +15,10 @@ import net.minecraft.core.particles.ParticleTypes; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; public class MeteorRainWeather extends AbstractWeather { @@ -42,12 +48,21 @@ public void tickBlock(ServerLevel level, int ticks, BlockPos pos) { int targetY = pos.getY(); int targetZ = pos.getZ(); RandomSource random = level.getRandom(); - AethersentMeteor meteor = new AethersentMeteor(level, null, targetX + (random.nextFloat() - 0.5) * 3, targetY + 200 + (random.nextFloat() - 0.5) * 5, targetZ + (random.nextFloat() - 0.5) * 3); - meteor.setSize(10); - meteor.setTargetPos(new Vec3(targetX, targetY, targetZ)); - meteor.setOnlyHurtEnemy(false); - level.addFreshEntity(meteor); - level.sendParticles(ParticleTypes.EXPLOSION, meteor.getX(), meteor.getY(), meteor.getZ(), 2, 0.2D, 0.2D, 0.2D, 0.0D); + if (ESConfig.INSTANCE.mobsConfig.creteor.canSpawn() && random.nextBoolean() && level.getEntitiesOfClass(Creteor.class, new AABB(pos).inflate(32)).isEmpty()) { + Creteor creteor = new Creteor(ESEntities.CRETEOR.get(), level); + creteor.setPos(targetX + (random.nextFloat() - 0.5) * 3, targetY + 200 + (random.nextFloat() - 0.5) * 5, targetZ + (random.nextFloat() - 0.5) * 3); + creteor.setPersistenceRequired(); + creteor.addEffect(new MobEffectInstance(MobEffects.GLOWING, 100)); + level.addFreshEntity(creteor); + level.sendParticles(ParticleTypes.EXPLOSION, creteor.getX(), creteor.getY(), creteor.getZ(), 2, 0.2D, 0.2D, 0.2D, 0.0D); + } else { + AethersentMeteor meteor = new AethersentMeteor(level, null, targetX + (random.nextFloat() - 0.5) * 3, targetY + 200 + (random.nextFloat() - 0.5) * 5, targetZ + (random.nextFloat() - 0.5) * 3); + meteor.setSize(10); + meteor.setTargetPos(new Vec3(targetX, targetY, targetZ)); + meteor.setOnlyHurtEnemy(false); + level.addFreshEntity(meteor); + level.sendParticles(ParticleTypes.EXPLOSION, meteor.getX(), meteor.getY(), meteor.getZ(), 2, 0.2D, 0.2D, 0.2D, 0.0D); + } } } diff --git a/common/src/main/resources/assets/eternal_starlight/lang/en_us.json b/common/src/main/resources/assets/eternal_starlight/lang/en_us.json index 961d4315..afdbb1af 100644 --- a/common/src/main/resources/assets/eternal_starlight/lang/en_us.json +++ b/common/src/main/resources/assets/eternal_starlight/lang/en_us.json @@ -226,7 +226,7 @@ "block.eternal_starlight.nebulaite_brick_stairs": "Nebulaite Brick Stairs", "block.eternal_starlight.nebulaite_brick_wall": "Nebulaite Brick Wall", "block.eternal_starlight.chiseled_nebulaite_bricks": "Chiseled Nebulaite Bricks", - "block.eternal_starlight.atalphaite_block": "Block of Atalphaite Block", + "block.eternal_starlight.atalphaite_block": "Block of Atalphaite", "block.eternal_starlight.blazing_atalphaite_block": "Block of Blazing Atalphaite", "block.eternal_starlight.atalphaite_light": "Atalphaite Light", "block.eternal_starlight.grimstone_atalphaite_ore": "Grimstone Atalphaite Ore", @@ -587,6 +587,8 @@ "item.eternal_starlight.lonestar_skeleton_spawn_egg": "Lonestar Skeleton Spawn Egg", "item.eternal_starlight.nightfall_spider_spawn_egg": "Nightfall Spider Spawn Egg", "item.eternal_starlight.thirst_walker_spawn_egg": "Thirst Walker Spawn Egg", + "item.eternal_starlight.creteor_spawn_egg": "Creteor Spawn Egg", + "item.eternal_starlight.tiny_creteor_spawn_egg": "Tiny Creteor Spawn Egg", "item.eternal_starlight.ent_spawn_egg": "Ent Spawn Egg", "item.eternal_starlight.ratlin_spawn_egg": "Ratlin Spawn Egg", "item.eternal_starlight.yeti_spawn_egg": "Yeti Spawn Egg", @@ -813,6 +815,8 @@ "entity.eternal_starlight.lonestar_skeleton": "Lonestar Skeleton", "entity.eternal_starlight.nightfall_spider": "Nightfall Spider", "entity.eternal_starlight.thirst_walker": "Thirst Walker", + "entity.eternal_starlight.creteor": "Creteor", + "entity.eternal_starlight.tiny_creteor": "Tiny Creteor", "entity.eternal_starlight.ent": "Ent", "entity.eternal_starlight.ratlin": "Ratlin", "entity.eternal_starlight.yeti": "Yeti", @@ -891,6 +895,11 @@ "subtitles.entity.eternal_starlight.thirst_walker.ambient": "Thirst Walker moans", "subtitles.entity.eternal_starlight.thirst_walker.hurt": "Thirst Walker hurts", "subtitles.entity.eternal_starlight.thirst_walker.death": "Thirst Walker dies", + "subtitles.entity.eternal_starlight.creteor.roll": "Creteor rolls", + "subtitles.entity.eternal_starlight.creteor.hurt": "Creteor hurts", + "subtitles.entity.eternal_starlight.creteor.death": "Creteor dies", + "subtitles.entity.eternal_starlight.creteor.charge": "Creteor charges", + "subtitles.entity.eternal_starlight.creteor.explode": "Creteor explodes", "subtitles.entity.eternal_starlight.luminofish.hurt": "Luminofish hurts", "subtitles.entity.eternal_starlight.luminofish.death": "Luminofish dies", "subtitles.entity.eternal_starlight.luminofish.flop": "Luminofish flops", diff --git a/common/src/main/resources/assets/eternal_starlight/lang/ja_jp.json b/common/src/main/resources/assets/eternal_starlight/lang/ja_jp.json index 74ad316c..bffeaf72 100644 --- a/common/src/main/resources/assets/eternal_starlight/lang/ja_jp.json +++ b/common/src/main/resources/assets/eternal_starlight/lang/ja_jp.json @@ -587,6 +587,8 @@ "item.eternal_starlight.lonestar_skeleton_spawn_egg": "孤星のスケルトンのスポーンエッグ", "item.eternal_starlight.nightfall_spider_spawn_egg": "夕暮れグモのスポーンエッグ", "item.eternal_starlight.thirst_walker_spawn_egg": "サーストウォーカーのスポーンエッグ", + "item.eternal_starlight.creteor_spawn_egg": "Creteor Spawn Egg", + "item.eternal_starlight.tiny_creteor_spawn_egg": "Tiny Creteor Spawn Egg", "item.eternal_starlight.ent_spawn_egg": "エントのスポーンエッグ", "item.eternal_starlight.ratlin_spawn_egg": "ラットリンのスポーンエッグ", "item.eternal_starlight.yeti_spawn_egg": "イエティのスポーンエッグ", @@ -813,6 +815,8 @@ "entity.eternal_starlight.lonestar_skeleton": "孤星のスケルトン", "entity.eternal_starlight.nightfall_spider": "夕暮れグモ", "entity.eternal_starlight.thirst_walker": "サーストウォーカー", + "entity.eternal_starlight.creteor": "Creteor", + "entity.eternal_starlight.tiny_creteor": "Tiny Creteor", "entity.eternal_starlight.ent": "エント", "entity.eternal_starlight.ratlin": "ラットリン", "entity.eternal_starlight.yeti": "イエティ", @@ -891,6 +895,11 @@ "subtitles.entity.eternal_starlight.thirst_walker.ambient": "サーストウォーカーがうめく", "subtitles.entity.eternal_starlight.thirst_walker.hurt": "サーストウォーカーがダメージを受ける", "subtitles.entity.eternal_starlight.thirst_walker.death": "サーストウォーカーが死ぬ", + "subtitles.entity.eternal_starlight.creteor.roll": "Creteor rolls", + "subtitles.entity.eternal_starlight.creteor.hurt": "Creteor hurts", + "subtitles.entity.eternal_starlight.creteor.death": "Creteor dies", + "subtitles.entity.eternal_starlight.creteor.charge": "Creteor charges", + "subtitles.entity.eternal_starlight.creteor.explode": "Creteor explodes", "subtitles.entity.eternal_starlight.luminofish.hurt": "ルミノフィッシュがダメージを受ける", "subtitles.entity.eternal_starlight.luminofish.death": "ルミノフィッシュが死ぬ", "subtitles.entity.eternal_starlight.luminofish.flop": "ルミノフィッシュが跳ねる", diff --git a/common/src/main/resources/assets/eternal_starlight/lang/ru_ru.json b/common/src/main/resources/assets/eternal_starlight/lang/ru_ru.json index 728b7dda..f817dea7 100644 --- a/common/src/main/resources/assets/eternal_starlight/lang/ru_ru.json +++ b/common/src/main/resources/assets/eternal_starlight/lang/ru_ru.json @@ -587,6 +587,8 @@ "item.eternal_starlight.lonestar_skeleton_spawn_egg": "Яйцо призыва звёздного скелета", "item.eternal_starlight.nightfall_spider_spawn_egg": "Яйцо призыва сумеречного паука", "item.eternal_starlight.thirst_walker_spawn_egg": "Яйцо призыва жаждущего странника", + "item.eternal_starlight.creteor_spawn_egg": "Creteor Spawn Egg", + "item.eternal_starlight.tiny_creteor_spawn_egg": "Tiny Creteor Spawn Egg", "item.eternal_starlight.ent_spawn_egg": "Яйцо призыва энта", "item.eternal_starlight.ratlin_spawn_egg": "Яйцо призыва крысёныша", "item.eternal_starlight.yeti_spawn_egg": "Яйцо призыва йети", @@ -813,6 +815,8 @@ "entity.eternal_starlight.lonestar_skeleton": "Звёздный скелет", "entity.eternal_starlight.nightfall_spider": "Сумеречный паук", "entity.eternal_starlight.thirst_walker": "Жаждущий странник", + "entity.eternal_starlight.creteor": "Creteor", + "entity.eternal_starlight.tiny_creteor": "Tiny Creteor", "entity.eternal_starlight.ent": "Энт", "entity.eternal_starlight.ratlin": "Крысёныш", "entity.eternal_starlight.yeti": "Йети", @@ -891,6 +895,11 @@ "subtitles.entity.eternal_starlight.thirst_walker.ambient": "Жаждущий странник стонет", "subtitles.entity.eternal_starlight.thirst_walker.hurt": "Жаждущий странник ранен", "subtitles.entity.eternal_starlight.thirst_walker.death": "Жаждущий странник стонет", + "subtitles.entity.eternal_starlight.creteor.roll": "Creteor rolls", + "subtitles.entity.eternal_starlight.creteor.hurt": "Creteor hurts", + "subtitles.entity.eternal_starlight.creteor.death": "Creteor dies", + "subtitles.entity.eternal_starlight.creteor.charge": "Creteor charges", + "subtitles.entity.eternal_starlight.creteor.explode": "Creteor explodes", "subtitles.entity.eternal_starlight.luminofish.hurt": "Светорыба ранена", "subtitles.entity.eternal_starlight.luminofish.death": "Светорыба стонет", "subtitles.entity.eternal_starlight.luminofish.flop": "Светорыба плещется", diff --git a/common/src/main/resources/assets/eternal_starlight/lang/zh_cn.json b/common/src/main/resources/assets/eternal_starlight/lang/zh_cn.json index ea3924e7..6cf5f91d 100644 --- a/common/src/main/resources/assets/eternal_starlight/lang/zh_cn.json +++ b/common/src/main/resources/assets/eternal_starlight/lang/zh_cn.json @@ -587,6 +587,8 @@ "item.eternal_starlight.lonestar_skeleton_spawn_egg": "孤星骷髅刷怪蛋", "item.eternal_starlight.nightfall_spider_spawn_egg": "夜幕蜘蛛刷怪蛋", "item.eternal_starlight.thirst_walker_spawn_egg": "饥渴行者刷怪蛋", + "item.eternal_starlight.creteor_spawn_egg": "苦彗怕刷怪蛋", + "item.eternal_starlight.tiny_creteor_spawn_egg": "小型苦彗怕刷怪蛋", "item.eternal_starlight.ent_spawn_egg": "树精刷怪蛋", "item.eternal_starlight.ratlin_spawn_egg": "硕鼠兽刷怪蛋", "item.eternal_starlight.yeti_spawn_egg": "雪怪刷怪蛋", @@ -813,6 +815,8 @@ "entity.eternal_starlight.lonestar_skeleton": "孤星骷髅", "entity.eternal_starlight.nightfall_spider": "夜幕蜘蛛", "entity.eternal_starlight.thirst_walker": "饥渴行者", + "entity.eternal_starlight.creteor": "苦彗怕", + "entity.eternal_starlight.tiny_creteor": "小型苦彗怕", "entity.eternal_starlight.ent": "树精", "entity.eternal_starlight.ratlin": "硕鼠兽", "entity.eternal_starlight.yeti": "雪怪", @@ -891,6 +895,11 @@ "subtitles.entity.eternal_starlight.thirst_walker.ambient": "饥渴行者:呻吟", "subtitles.entity.eternal_starlight.thirst_walker.hurt": "饥渴行者:受伤", "subtitles.entity.eternal_starlight.thirst_walker.death": "饥渴行者:死亡", + "subtitles.entity.eternal_starlight.creteor.roll": "苦彗怕:滚动", + "subtitles.entity.eternal_starlight.creteor.hurt": "苦彗怕:受伤", + "subtitles.entity.eternal_starlight.creteor.death": "苦彗怕:死亡", + "subtitles.entity.eternal_starlight.creteor.charge": "苦彗怕:蓄力", + "subtitles.entity.eternal_starlight.creteor.explode": "苦彗怕:爆炸", "subtitles.entity.eternal_starlight.luminofish.hurt": "光鲀:受伤", "subtitles.entity.eternal_starlight.luminofish.death": "光鲀:死亡", "subtitles.entity.eternal_starlight.luminofish.flop": "光鲀:挣扎", @@ -1005,17 +1014,17 @@ "death.attack.eternal_starlight.poison.player": "%1$s在逃离%2$s时因剧毒而死", "death.attack.eternal_starlight.bite": "%1$s被咬死了", "death.attack.eternal_starlight.bite.player": "%1$s在逃离%2$s时被咬死了", - "trim_material.eternal_starlight.red_starlight_crystal": "红色星光水晶材料", - "trim_material.eternal_starlight.blue_starlight_crystal": "蓝色星光水晶材料", - "trim_material.eternal_starlight.thioquartz": "石英硫材料", - "trim_material.eternal_starlight.aethersent": "天赐材料", - "trim_material.eternal_starlight.thermal_springstone": "热泉石材料", - "trim_material.eternal_starlight.glacite": "永冻石材料", - "trim_material.eternal_starlight.swamp_silver": "沼泽银材料", - "trim_material.eternal_starlight.amaramber": "绯夜脂材料", - "trim_material.eternal_starlight.golem_steel": "傀儡钢材料", - "trim_material.eternal_starlight.moonring": "月珥材料", - "trim_material.eternal_starlight.doomeden_bone": "魔窟断骨材料", + "trim_material.eternal_starlight.red_starlight_crystal": "红色星光水晶质", + "trim_material.eternal_starlight.blue_starlight_crystal": "蓝色星光水晶质", + "trim_material.eternal_starlight.thioquartz": "石英硫质", + "trim_material.eternal_starlight.aethersent": "天赐质", + "trim_material.eternal_starlight.thermal_springstone": "热泉石质", + "trim_material.eternal_starlight.glacite": "永冻石质", + "trim_material.eternal_starlight.swamp_silver": "沼泽银质", + "trim_material.eternal_starlight.amaramber": "绯夜脂质", + "trim_material.eternal_starlight.golem_steel": "傀儡钢质", + "trim_material.eternal_starlight.moonring": "月珥质", + "trim_material.eternal_starlight.doomeden_bone": "魔窟断骨质", "trim_pattern.eternal_starlight.keeper": "守御盔甲纹饰", "trim_pattern.eternal_starlight.forge": "锻造盔甲纹饰", "mana_type.eternal_starlight.terra": "地", diff --git a/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/charge.ogg b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/charge.ogg new file mode 100644 index 00000000..0008a904 Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/charge.ogg differ diff --git a/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/death.ogg b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/death.ogg new file mode 100644 index 00000000..e7a18245 Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/death.ogg differ diff --git a/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/explode.ogg b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/explode.ogg new file mode 100644 index 00000000..a44ca584 Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/explode.ogg differ diff --git a/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt1.ogg b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt1.ogg new file mode 100644 index 00000000..3a036f25 Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt1.ogg differ diff --git a/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt2.ogg b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt2.ogg new file mode 100644 index 00000000..85fa0925 Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt2.ogg differ diff --git a/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt3.ogg b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt3.ogg new file mode 100644 index 00000000..f5021c27 Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt3.ogg differ diff --git a/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt4.ogg b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt4.ogg new file mode 100644 index 00000000..44ebd17f Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/hurt4.ogg differ diff --git a/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/roll.ogg b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/roll.ogg new file mode 100644 index 00000000..5466e2b9 Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/sounds/mob/creteor/roll.ogg differ diff --git a/common/src/main/resources/assets/eternal_starlight/textures/block/haze_ice_bricks.png b/common/src/main/resources/assets/eternal_starlight/textures/block/haze_ice_bricks.png index ec325c00..fc523455 100644 Binary files a/common/src/main/resources/assets/eternal_starlight/textures/block/haze_ice_bricks.png and b/common/src/main/resources/assets/eternal_starlight/textures/block/haze_ice_bricks.png differ diff --git a/common/src/main/resources/assets/eternal_starlight/textures/entity/creteor.png b/common/src/main/resources/assets/eternal_starlight/textures/entity/creteor.png new file mode 100644 index 00000000..abb8943d Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/textures/entity/creteor.png differ diff --git a/common/src/main/resources/assets/eternal_starlight/textures/entity/tiny_creteor.png b/common/src/main/resources/assets/eternal_starlight/textures/entity/tiny_creteor.png new file mode 100644 index 00000000..827d8b1e Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/textures/entity/tiny_creteor.png differ diff --git a/common/src/main/resources/assets/eternal_starlight/textures/particle/explosion_shock.png b/common/src/main/resources/assets/eternal_starlight/textures/particle/explosion_shock.png new file mode 100644 index 00000000..9eb5f9cb Binary files /dev/null and b/common/src/main/resources/assets/eternal_starlight/textures/particle/explosion_shock.png differ diff --git a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/ESParticleDescriptionProvider.java b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/ESParticleDescriptionProvider.java index f18ea3c0..810d4071 100644 --- a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/ESParticleDescriptionProvider.java +++ b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/ESParticleDescriptionProvider.java @@ -28,6 +28,7 @@ protected void addDescriptions() { sprite(ESParticles.GLOW.get(), loc("glow")); sprite(ESParticles.AETHERSENT_SMOKE.get(), loc("big_smoke_3")); spriteSet(ESParticles.ASHEN_SNOW.get(), loc("ashen_snow"), 4, false); + sprite(ESParticles.EXPLOSION_SHOCK.get(), loc("explosion_shock")); sprite(ESParticles.ADVANCED_GLOW.get(), loc("glow")); sprite(ESParticles.SHINE.get(), loc("shine")); } diff --git a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/ESSoundProvider.java b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/ESSoundProvider.java index 99651b18..9fef0332 100644 --- a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/ESSoundProvider.java +++ b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/ESSoundProvider.java @@ -85,6 +85,12 @@ public void registerSounds() { add(ESSoundEvents.THIRST_WALKER_HURT.get(), definition().with(sound(loc("mob/thirst_walker/hurt1")), sound(loc("mob/thirst_walker/hurt2"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".thirst_walker.hurt")); add(ESSoundEvents.THIRST_WALKER_DEATH.get(), definition().with(sound(loc("mob/thirst_walker/death"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".thirst_walker.death")); + add(ESSoundEvents.CRETEOR_ROLL.get(), definition().with(sound(loc("mob/creteor/roll"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".creteor.roll")); + add(ESSoundEvents.CRETEOR_HURT.get(), definition().with(sound(loc("mob/creteor/hurt1")), sound(loc("mob/creteor/hurt2")), sound(loc("mob/creteor/hurt3")), sound(loc("mob/creteor/hurt4"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".creteor.hurt")); + add(ESSoundEvents.CRETEOR_DEATH.get(), definition().with(sound(loc("mob/creteor/death"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".creteor.death")); + add(ESSoundEvents.CRETEOR_CHARGE.get(), definition().with(sound(loc("mob/creteor/charge"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".creteor.charge")); + add(ESSoundEvents.CRETEOR_EXPLODE.get(), definition().with(sound(loc("mob/creteor/explode"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".creteor.explode")); + add(ESSoundEvents.LUMINOFISH_HURT.get(), definition().with(sound(mcLoc("entity/fish/hurt1")), sound(mcLoc("entity/fish/hurt2")), sound(mcLoc("entity/fish/hurt3")), sound(mcLoc("entity/fish/hurt4"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".luminofish.hurt")); add(ESSoundEvents.LUMINOFISH_DEATH.get(), definition().with(sound(mcLoc("entity/fish/hurt1")), sound(mcLoc("entity/fish/hurt2")), sound(mcLoc("entity/fish/hurt3")), sound(mcLoc("entity/fish/hurt4"))).subtitle("subtitles.entity." + EternalStarlight.ID + ".luminofish.death")); add(ESSoundEvents.LUMINOFISH_FLOP.get(), definition().with(sound(mcLoc("entity/fish/flop1")).volume(0.3), sound(mcLoc("entity/fish/flop2")).volume(0.3), sound(mcLoc("entity/fish/flop3")).volume(0.3), sound(mcLoc("entity/fish/flop4")).volume(0.3)).subtitle("subtitles.entity." + EternalStarlight.ID + ".luminofish.flop")); diff --git a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/loot/ESEntityLootSubProvider.java b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/loot/ESEntityLootSubProvider.java index 5a217803..c438a7c5 100644 --- a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/loot/ESEntityLootSubProvider.java +++ b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/loot/ESEntityLootSubProvider.java @@ -58,6 +58,14 @@ public void generate() { .when(LootItemRandomChanceCondition.randomChance(0.4f)) .add(LootItem.lootTableItem(ESItems.TOOTH_OF_HUNGER.get()).apply(SetItemCountFunction.setCount(UniformGenerator.between(1.0F, 3.0F))).apply(EnchantedCountIncreaseFunction.lootingMultiplier(registries, UniformGenerator.between(0.0F, 1.0F)))))); + add(ESEntities.CRETEOR.get(), LootTable.lootTable() + .withPool(LootPool.lootPool().setRolls(ConstantValue.exactly(1.0F)) + .add(LootItem.lootTableItem(ESItems.RAW_AETHERSENT.get()).apply(SetItemCountFunction.setCount(UniformGenerator.between(3.0F, 5.0F))).apply(EnchantedCountIncreaseFunction.lootingMultiplier(registries, UniformGenerator.between(0.0F, 1.0F)))))); + + add(ESEntities.TINY_CRETEOR.get(), LootTable.lootTable() + .withPool(LootPool.lootPool().setRolls(ConstantValue.exactly(1.0F)) + .add(LootItem.lootTableItem(ESItems.RAW_AETHERSENT.get()).apply(SetItemCountFunction.setCount(UniformGenerator.between(1.0F, 3.0F))).apply(EnchantedCountIncreaseFunction.lootingMultiplier(registries, UniformGenerator.between(0.0F, 1.0F)))))); + add(ESEntities.ENT.get(), LootTable.lootTable() .withPool(LootPool.lootPool().setRolls(ConstantValue.exactly(1.0F)) .add(LootItem.lootTableItem(Items.STICK).apply(SetItemCountFunction.setCount(UniformGenerator.between(0.0F, 2.0F))).apply(EnchantedCountIncreaseFunction.lootingMultiplier(registries, UniformGenerator.between(0.0F, 1.0F))))) diff --git a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/model/ESItemModelProvider.java b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/model/ESItemModelProvider.java index de92e904..e81b77f6 100644 --- a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/model/ESItemModelProvider.java +++ b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/model/ESItemModelProvider.java @@ -28,6 +28,8 @@ protected void registerModels() { spawnEgg(ESItems.LONESTAR_SKELETON_SPAWN_EGG.get()); spawnEgg(ESItems.NIGHTFALL_SPIDER_SPAWN_EGG.get()); spawnEgg(ESItems.THIRST_WALKER_SPAWN_EGG.get()); + spawnEgg(ESItems.CRETEOR_SPAWN_EGG.get()); + spawnEgg(ESItems.TINY_CRETEOR_SPAWN_EGG.get()); spawnEgg(ESItems.ENT_SPAWN_EGG.get()); spawnEgg(ESItems.RATLIN_SPAWN_EGG.get()); spawnEgg(ESItems.YETI_SPAWN_EGG.get()); diff --git a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/tags/ESEntityTypeTagsProvider.java b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/tags/ESEntityTypeTagsProvider.java index edffa283..4be977a5 100644 --- a/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/tags/ESEntityTypeTagsProvider.java +++ b/neoforge/src/main/java/cn/leolezury/eternalstarlight/neoforge/datagen/provider/tags/ESEntityTypeTagsProvider.java @@ -87,6 +87,8 @@ protected void addTags(HolderLookup.Provider lookupProvider) { ); tag(EntityTypeTags.FALL_DAMAGE_IMMUNE).add( ESEntities.ASTRAL_GOLEM.get(), + ESEntities.CRETEOR.get(), + ESEntities.TINY_CRETEOR.get(), ESEntities.CRYSTALLIZED_MOTH.get(), ESEntities.SHIMMER_LACEWING.get(), ESEntities.GRIMSTONE_GOLEM.get()