diff --git a/src/api/java/de/teamlapen/vampirism/api/entity/player/actions/IActionHandler.java b/src/api/java/de/teamlapen/vampirism/api/entity/player/actions/IActionHandler.java index 5d4a62f051..5004d4a74f 100755 --- a/src/api/java/de/teamlapen/vampirism/api/entity/player/actions/IActionHandler.java +++ b/src/api/java/de/teamlapen/vampirism/api/entity/player/actions/IActionHandler.java @@ -2,6 +2,7 @@ import com.google.common.collect.ImmutableList; +import de.teamlapen.vampirism.api.VampirismAPI; import de.teamlapen.vampirism.api.VampirismRegistries; import de.teamlapen.vampirism.api.annotations.FloatRange; import de.teamlapen.vampirism.api.entity.player.IFactionPlayer; @@ -9,11 +10,13 @@ import de.teamlapen.vampirism.api.util.RegUtil; import net.minecraft.core.Holder; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -21,6 +24,10 @@ */ public interface IActionHandler & ISkillPlayer> { + static > Optional> get(Player player) { + return VampirismAPI.factionPlayerHandler(player).getActionHandler(); + } + /** * Deactivate any active action and start cooldown timer */ diff --git a/src/generated/resources/assets/vampirism/particles/mist_smoke.json b/src/generated/resources/assets/vampirism/particles/mist_smoke.json new file mode 100644 index 0000000000..271261099b --- /dev/null +++ b/src/generated/resources/assets/vampirism/particles/mist_smoke.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "minecraft:generic_7", + "minecraft:generic_6", + "minecraft:generic_5", + "minecraft:generic_4", + "minecraft:generic_3", + "minecraft:generic_2", + "minecraft:generic_1", + "minecraft:generic_0" + ] +} \ No newline at end of file diff --git a/src/main/java/de/teamlapen/vampirism/client/core/ModParticleFactories.java b/src/main/java/de/teamlapen/vampirism/client/core/ModParticleFactories.java index 2d2f2c74ce..4c24c1a098 100644 --- a/src/main/java/de/teamlapen/vampirism/client/core/ModParticleFactories.java +++ b/src/main/java/de/teamlapen/vampirism/client/core/ModParticleFactories.java @@ -3,6 +3,7 @@ import de.teamlapen.vampirism.client.particle.FlyingBloodEntityParticle; import de.teamlapen.vampirism.client.particle.FlyingBloodParticle; import de.teamlapen.vampirism.client.particle.GenericParticle; +import de.teamlapen.vampirism.client.particle.MistSmokeParticle; import de.teamlapen.vampirism.core.ModParticles; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; @@ -16,5 +17,6 @@ static void registerFactories(@NotNull RegisterParticleProvidersEvent event) { event.registerSpecial(ModParticles.FLYING_BLOOD.get(), new FlyingBloodParticle.Factory()); event.registerSpecial(ModParticles.FLYING_BLOOD_ENTITY.get(), new FlyingBloodEntityParticle.Factory()); event.registerSpecial(ModParticles.GENERIC.get(), new GenericParticle.Factory()); + event.registerSpriteSet(ModParticles.MIST_SMOKE.get(), MistSmokeParticle.Provider::new); } } diff --git a/src/main/java/de/teamlapen/vampirism/client/particle/MistSmokeParticle.java b/src/main/java/de/teamlapen/vampirism/client/particle/MistSmokeParticle.java new file mode 100644 index 0000000000..6cf8633a18 --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/client/particle/MistSmokeParticle.java @@ -0,0 +1,55 @@ +package de.teamlapen.vampirism.client.particle; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleProvider; +import net.minecraft.client.particle.SimpleAnimatedParticle; +import net.minecraft.client.particle.SpriteSet; +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.SimpleParticleType; +import net.minecraft.util.FastColor; +import org.jetbrains.annotations.NotNull; + +public class MistSmokeParticle extends SimpleAnimatedParticle { + + MistSmokeParticle(ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed, int pPackedColor, SpriteSet pSprites) { + super(pLevel, pX, pY, pZ, pSprites, 0.0F); + this.friction = 0.92F; + this.quadSize = 0.5F; + this.setAlpha(0.8F); + this.setColor(1, 1, 1); + this.lifetime = (int)((double)(this.quadSize * 12.0F) / (Math.random() * 0.8F + 0.2F)); + this.setSpriteFromAge(pSprites); + this.hasPhysics = false; + this.xd = pXSpeed; + this.yd = pYSpeed; + this.zd = pZSpeed; + } + + @Override + public void tick() { + super.tick(); + if (!this.removed) { + this.setSpriteFromAge(this.sprites); + if (this.age > this.lifetime / 2) { + this.setAlpha((1.0F - ((float)this.age - (float)(this.lifetime / 2)) / (float)this.lifetime) * 0.8f); + } + + if (this.level.getBlockState(BlockPos.containing(this.x, this.y, this.z)).isAir()) { + this.yd -= 0.0074F; + } + } + } + + public static class Provider implements ParticleProvider { + private final SpriteSet sprites; + + public Provider(SpriteSet pSprites) { + this.sprites = pSprites; + } + + public Particle createParticle(@NotNull SimpleParticleType pType, @NotNull ClientLevel pLevel, double pX, double pY, double pZ, double pXSpeed, double pYSpeed, double pZSpeed) { + return new MistSmokeParticle(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed, FastColor.ARGB32.color(128, 255, 255, 255), this.sprites); + } + } +} diff --git a/src/main/java/de/teamlapen/vampirism/client/renderer/RenderHandler.java b/src/main/java/de/teamlapen/vampirism/client/renderer/RenderHandler.java index f2320d89a5..d9a1060b82 100644 --- a/src/main/java/de/teamlapen/vampirism/client/renderer/RenderHandler.java +++ b/src/main/java/de/teamlapen/vampirism/client/renderer/RenderHandler.java @@ -4,16 +4,20 @@ import de.teamlapen.lib.util.OptifineHandler; import de.teamlapen.vampirism.api.entity.IExtendedCreatureVampirism; import de.teamlapen.vampirism.api.entity.hunter.IHunterMob; +import de.teamlapen.vampirism.api.entity.player.actions.IActionHandler; +import de.teamlapen.vampirism.api.entity.player.vampire.IVampirePlayer; import de.teamlapen.vampirism.api.items.IItemWithTier; import de.teamlapen.vampirism.api.util.VResourceLocation; import de.teamlapen.vampirism.blocks.CoffinBlock; import de.teamlapen.vampirism.config.VampirismConfig; import de.teamlapen.vampirism.core.ModAttachments; +import de.teamlapen.vampirism.core.ModParticles; import de.teamlapen.vampirism.core.ModRefinements; import de.teamlapen.vampirism.entity.ExtendedCreature; import de.teamlapen.vampirism.entity.player.VampirismPlayerAttributes; import de.teamlapen.vampirism.entity.player.vampire.VampirePlayer; import de.teamlapen.vampirism.entity.player.vampire.VampirePlayerSpecialAttributes; +import de.teamlapen.vampirism.entity.player.vampire.actions.VampireActions; import de.teamlapen.vampirism.items.CrucifixItem; import de.teamlapen.vampirism.mixin.client.accessor.CameraAccessor; import de.teamlapen.vampirism.util.Helper; @@ -181,6 +185,14 @@ public void onRenderHand(@NotNull RenderHandEvent event) { } } + @SubscribeEvent + public void onRenderLivingPost(RenderPlayerEvent.@NotNull Post event) + { + if (event.getEntity().tickCount % 2 == 0 && IActionHandler.get(event.getEntity()).map(s -> s.isActionActive(VampireActions.HALF_INVULNERABLE)).orElse(false)) { + event.getEntity().level().addParticle(ModParticles.MIST_SMOKE.get(), event.getEntity().getRandomX(0.2), event.getEntity().getY() + event.getEntity().getBbHeight() / 2 + event.getEntity().getRandom().nextDouble() * 0.2f, event.getEntity().getRandomZ(0.2), 0, 0, 0); + } + } + @SubscribeEvent public void onRenderLivingPost(RenderLivingEvent.@NotNull Post event) { if (!isInsideBloodVisionRendering && shouldRenderBloodVision() && !reducedBloodVision) { diff --git a/src/main/java/de/teamlapen/vampirism/core/ModParticles.java b/src/main/java/de/teamlapen/vampirism/core/ModParticles.java index 94abb3c310..c04a1f714f 100644 --- a/src/main/java/de/teamlapen/vampirism/core/ModParticles.java +++ b/src/main/java/de/teamlapen/vampirism/core/ModParticles.java @@ -7,6 +7,7 @@ import de.teamlapen.vampirism.particle.GenericParticleOptions; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; +import net.minecraft.core.particles.SimpleParticleType; import net.minecraft.core.registries.Registries; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; @@ -56,6 +57,7 @@ public class ModParticles { return GenericParticleOptions.STREAM_CODEC; } }); + public static final DeferredHolder, SimpleParticleType> MIST_SMOKE = PARTICLE_TYPES.register("mist_smoke", () -> new SimpleParticleType(true)); static void register(IEventBus bus) { PARTICLE_TYPES.register(bus); diff --git a/src/main/java/de/teamlapen/vampirism/data/provider/DataProvider.java b/src/main/java/de/teamlapen/vampirism/data/provider/DataProvider.java index 47b891441e..987c7f6926 100644 --- a/src/main/java/de/teamlapen/vampirism/data/provider/DataProvider.java +++ b/src/main/java/de/teamlapen/vampirism/data/provider/DataProvider.java @@ -43,5 +43,6 @@ public static void onGatherData(GatherDataEvent event) { generator.addProvider(event.includeServer(), new SkillTreeProvider(packOutput, lookupProviderFuture)); generator.addProvider(event.includeServer(), new DataMapsProvider(packOutput, lookupProviderFuture)); generator.addProvider(event.includeServer(), new LootModifierGenerator(packOutput, lookupProviderFuture)); + generator.addProvider(event.includeClient(), new ModParticleDescriptionProvider(packOutput, existingFileHelper)); } } diff --git a/src/main/java/de/teamlapen/vampirism/data/provider/ModParticleDescriptionProvider.java b/src/main/java/de/teamlapen/vampirism/data/provider/ModParticleDescriptionProvider.java new file mode 100644 index 0000000000..8c3465d15b --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/data/provider/ModParticleDescriptionProvider.java @@ -0,0 +1,19 @@ +package de.teamlapen.vampirism.data.provider; + +import de.teamlapen.vampirism.api.util.VResourceLocation; +import de.teamlapen.vampirism.core.ModParticles; +import net.minecraft.data.PackOutput; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import net.neoforged.neoforge.common.data.ParticleDescriptionProvider; + +public class ModParticleDescriptionProvider extends ParticleDescriptionProvider { + + protected ModParticleDescriptionProvider(PackOutput output, ExistingFileHelper fileHelper) { + super(output, fileHelper); + } + + @Override + protected void addDescriptions() { + spriteSet(ModParticles.MIST_SMOKE.get(), VResourceLocation.mc("generic"), 8, true); + } +} diff --git a/src/main/java/de/teamlapen/vampirism/mixin/client/LivingEntityRendererMixin.java b/src/main/java/de/teamlapen/vampirism/mixin/client/LivingEntityRendererMixin.java new file mode 100644 index 0000000000..bd96da7102 --- /dev/null +++ b/src/main/java/de/teamlapen/vampirism/mixin/client/LivingEntityRendererMixin.java @@ -0,0 +1,49 @@ +package de.teamlapen.vampirism.mixin.client; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import de.teamlapen.vampirism.api.entity.player.actions.IActionHandler; +import de.teamlapen.vampirism.api.entity.player.vampire.IVampirePlayer; +import de.teamlapen.vampirism.entity.player.vampire.actions.VampireActions; +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.FastColor; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LivingEntityRenderer.class) +public abstract class LivingEntityRendererMixin> extends EntityRenderer { + + protected LivingEntityRendererMixin(EntityRendererProvider.Context pContext) { + super(pContext); + } + + @Inject(method= "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at= @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/MultiBufferSource;getBuffer(Lnet/minecraft/client/renderer/RenderType;)Lcom/mojang/blaze3d/vertex/VertexConsumer;", shift = At.Shift.BEFORE)) + private void test(T pEntity, float pEntityYaw, float pPartialTicks, PoseStack pPoseStack, MultiBufferSource pBuffer, int pPackedLight, CallbackInfo ci, @Local(name = "rendertype") LocalRef renderType, @Local(name = "flag") boolean flag, @Local(name = "flag1") boolean flag1, @Share("mist") LocalBooleanRef mist) { + if (flag && !flag1 && pEntity instanceof Player player && IActionHandler.get(player).map(s -> s.isActionActive(VampireActions.HALF_INVULNERABLE)).orElse(false)) { + ResourceLocation resourcelocation = this.getTextureLocation(pEntity); + renderType.set(RenderType.itemEntityTranslucentCull(resourcelocation)); + mist.set(true); + } + } + + @WrapOperation(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/EntityModel;renderToBuffer(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;III)V")) + private void changeColor(EntityModel instance, PoseStack poseStack, VertexConsumer consumer, int i1, int i2, int i3, Operation original, @Share("mist") LocalBooleanRef mist) { + original.call(instance, poseStack, consumer, i1, i2, mist.get() ? FastColor.ARGB32.color(0,255,255,255) : i3); + } +} diff --git a/src/main/resources/vampirism.mixins.json b/src/main/resources/vampirism.mixins.json index c10e394433..053d05238a 100644 --- a/src/main/resources/vampirism.mixins.json +++ b/src/main/resources/vampirism.mixins.json @@ -61,6 +61,7 @@ "client": [ "client.HumanoidArmorLayerMixin", "client.LevelRendererMixin", + "client.LivingEntityRendererMixin", "client.MinecraftMixin", "client.ResourceLoadStateTrackerMixin", "client.StatsScreenMixin",