From a163daf67318f2db6b397ae3f96cdfc906cc313d Mon Sep 17 00:00:00 2001 From: Redfan <114088095+Redfan2@users.noreply.github.com> Date: Sun, 29 Sep 2024 00:18:32 +0200 Subject: [PATCH 1/4] Warden Posession First Prototype --- build.gradle | 17 +- gradle.properties | 1 + gradle/compat-libs.versions.toml | 2 + gradle/wrapper/gradle-wrapper.properties | 2 +- requiem-api/src/main/resources/quilt.mod.json | 3 +- .../requiem/client/RequiemClient.java | 2 + .../requiem/client/RequiemClientListener.java | 1 + .../client/RequiemEntityShaderPicker.java | 4 + .../client/particle/SoundParticle.java | 178 ++++++++++++++++ .../requiem/common/RequiemComponents.java | 2 + .../entity/internal/WardenExtension.java | 45 +++++ .../entity/warden/WardenSensedComponent.java | 145 +++++++++++++ .../common/particle/RequiemParticleTypes.java | 3 + .../EntityRenderDispatcherMixin.java | 31 +++ .../nightvision/BackgroundRendererMixin.java | 2 + .../wardenvision/BackgroundRendererMixin.java | 121 +++++++++++ .../wardenvision/MinecraftClientMixin.java | 61 ++++++ .../possession/gameplay/ServerWorldMixin.java | 76 +++++++ .../possession/gameplay/WardenMixin.java | 146 +++++++++++++ .../assets/requiem/particles/sound.json | 12 ++ .../assets/requiem/shaders/post/warden.json | 17 ++ .../assets/requiem/shaders/program/warden.fsh | 191 ++++++++++++++++++ .../requiem/shaders/program/warden.json | 59 ++++++ .../requiem/textures/particle/sound_0.png | Bin 0 -> 137 bytes .../requiem/textures/particle/sound_1.png | Bin 0 -> 146 bytes .../requiem/textures/particle/sound_2.png | Bin 0 -> 157 bytes .../requiem/textures/particle/sound_3.png | Bin 0 -> 168 bytes .../requiem/textures/particle/sound_4.png | Bin 0 -> 178 bytes .../requiem/textures/particle/sound_5.png | Bin 0 -> 188 bytes .../requiem/textures/particle/sound_6.png | Bin 0 -> 198 bytes .../requiem/textures/particle/sound_7.png | Bin 0 -> 191 bytes src/main/resources/mixins.requiem.client.json | 4 + src/main/resources/mixins.requiem.common.json | 2 + src/main/resources/requiem.accesswidener | 10 + 34 files changed, 1134 insertions(+), 3 deletions(-) create mode 100644 src/main/java/ladysnake/requiem/client/particle/SoundParticle.java create mode 100644 src/main/java/ladysnake/requiem/common/entity/internal/WardenExtension.java create mode 100644 src/main/java/ladysnake/requiem/common/entity/warden/WardenSensedComponent.java create mode 100644 src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/BackgroundRendererMixin.java create mode 100644 src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/MinecraftClientMixin.java create mode 100644 src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerWorldMixin.java create mode 100644 src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java create mode 100644 src/main/resources/assets/requiem/particles/sound.json create mode 100644 src/main/resources/assets/requiem/shaders/post/warden.json create mode 100644 src/main/resources/assets/requiem/shaders/program/warden.fsh create mode 100644 src/main/resources/assets/requiem/shaders/program/warden.json create mode 100644 src/main/resources/assets/requiem/textures/particle/sound_0.png create mode 100644 src/main/resources/assets/requiem/textures/particle/sound_1.png create mode 100644 src/main/resources/assets/requiem/textures/particle/sound_2.png create mode 100644 src/main/resources/assets/requiem/textures/particle/sound_3.png create mode 100644 src/main/resources/assets/requiem/textures/particle/sound_4.png create mode 100644 src/main/resources/assets/requiem/textures/particle/sound_5.png create mode 100644 src/main/resources/assets/requiem/textures/particle/sound_6.png create mode 100644 src/main/resources/assets/requiem/textures/particle/sound_7.png create mode 100644 src/main/resources/requiem.accesswidener diff --git a/build.gradle b/build.gradle index 011172408..7427a363a 100644 --- a/build.gradle +++ b/build.gradle @@ -128,6 +128,12 @@ allprojects { compileOnly metaLibs.bundles.devAnnotations } + + //Fixes Crash with duplicate QuiltLoader and FAPI + project.configurations.configureEach { + exclude(group: "net.fabricmc", module: "fabric-loader") + exclude(group: "net.fabricmc.fabric-api") + } } chenille { @@ -183,7 +189,8 @@ dependencies { // modLocalRuntime compatLibs.biomeMakeover modCompileOnly (compatLibs.trinkets) { transitive = false } // modLocalRuntime compatLibs.trinkets - modCompileOnly (compatLibs.pehkui) { transitive = false } + //Doesn't resolve it because Curseforge's Maven times out + //modCompileOnly (compatLibs.pehkui) { transitive = true } // modApi (compatLibs.pehkui) { transitive = false } modCompileOnly (compatLibs.snowmercy) { transitive = false } @@ -219,6 +226,14 @@ dependencies { remapJar.dependsOn(project(":requiem-core").tasks.remapJar) +loom { + mods { + "requiem" { + accessWidenerPath = file("src/main/resources/requiem.accesswidener") + } + } +} + jar { from 'LICENSE-CODE' from 'LICENSE-ART' diff --git a/gradle.properties b/gradle.properties index 7fad92cbd..2ee85b1dd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,7 @@ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. org.gradle.jvmargs = -Xmx4G +org.gradle.parallel=false # Base properties mod_version = 2.0.0-beta.17 diff --git a/gradle/compat-libs.versions.toml b/gradle/compat-libs.versions.toml index 63061d180..4af1edaad 100644 --- a/gradle/compat-libs.versions.toml +++ b/gradle/compat-libs.versions.toml @@ -51,6 +51,8 @@ mobz = { group = "curse.maven", name = "mobz-336554", versi omegaConfig = { group = "com.github.Draylar.omega-config", name = "omega-config-base", version.ref = "omegaConfig" } origins = { group = "maven.modrinth", name = "origins", version.ref = "origins" } patchouli = { group = "vazkii.patchouli", name = "Patchouli", version.ref = "patchouli" } +# The version from Github didn't compile because it couldn't find KanosConfig. According to Jitpack's log, it made a GET request to the Curseforge Maven which was answered with 522: Connection timed out TODO: by:Redfan2: Investigate Pehkui +#pehkui = { module= "maven.modrinth:pehkui", version.ref = "pehkui" } pehkui = { module= "com.github.Virtuoel:Pehkui", version.ref = "pehkui" } kano_config = { module= "com.github.Virtuoel:KanosConfig", version.ref = "kano"} snowmercy = { module = "io.github.ladysnake:Snow-Mercy", version.ref = "snowmercy" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0d1842103..e1adfb493 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/requiem-api/src/main/resources/quilt.mod.json b/requiem-api/src/main/resources/quilt.mod.json index 28d49ceed..0aa964c93 100644 --- a/requiem-api/src/main/resources/quilt.mod.json +++ b/requiem-api/src/main/resources/quilt.mod.json @@ -60,6 +60,7 @@ "requiem:soul_holder", "requiem:charged_jump", "requiem:rift_tracker", - "requiem:dropped_vessel_tracker" + "requiem:dropped_vessel_tracker", + "requiem:warden_sensed" ] } diff --git a/src/main/java/ladysnake/requiem/client/RequiemClient.java b/src/main/java/ladysnake/requiem/client/RequiemClient.java index 0f96fa717..c9f824415 100644 --- a/src/main/java/ladysnake/requiem/client/RequiemClient.java +++ b/src/main/java/ladysnake/requiem/client/RequiemClient.java @@ -42,6 +42,7 @@ import ladysnake.requiem.client.particle.CureParticle; import ladysnake.requiem.client.particle.EntityDustParticle; import ladysnake.requiem.client.particle.GhostParticle; +import ladysnake.requiem.client.particle.SoundParticle; import ladysnake.requiem.client.particle.wisp.WispTrailParticle; import ladysnake.requiem.client.render.block.RunestoneBlockEntityRenderer; import ladysnake.requiem.client.render.entity.CuredPiglinEntityRenderer; @@ -193,6 +194,7 @@ private void registerParticleFactories() { registry.register(RequiemParticleTypes.OBELISK_SOUL, SoulParticle.Factory::new); registry.register(RequiemParticleTypes.SOUL_TRAIL, WispTrailParticle.Factory::new); registry.register(RequiemParticleTypes.PENANCE, SpellParticle.EntityFactory::new); + registry.register(RequiemParticleTypes.SOUND, SoundParticle.Factory::new); } private void registerModelPredicates() { diff --git a/src/main/java/ladysnake/requiem/client/RequiemClientListener.java b/src/main/java/ladysnake/requiem/client/RequiemClientListener.java index d017a5acd..1ccb124c7 100644 --- a/src/main/java/ladysnake/requiem/client/RequiemClientListener.java +++ b/src/main/java/ladysnake/requiem/client/RequiemClientListener.java @@ -64,6 +64,7 @@ import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.ShulkerEntity; import net.minecraft.entity.mob.WitchEntity; +import net.minecraft.entity.mob.warden.WardenEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BowItem; import net.minecraft.item.CrossbowItem; diff --git a/src/main/java/ladysnake/requiem/client/RequiemEntityShaderPicker.java b/src/main/java/ladysnake/requiem/client/RequiemEntityShaderPicker.java index 255bc94cd..17b02da49 100644 --- a/src/main/java/ladysnake/requiem/client/RequiemEntityShaderPicker.java +++ b/src/main/java/ladysnake/requiem/client/RequiemEntityShaderPicker.java @@ -43,6 +43,7 @@ import net.minecraft.client.gl.ShaderEffect; import net.minecraft.entity.Entity; import net.minecraft.entity.mob.WaterCreatureEntity; +import net.minecraft.entity.mob.warden.WardenEntity; import net.minecraft.entity.passive.BeeEntity; import net.minecraft.entity.passive.DolphinEntity; import net.minecraft.entity.passive.MooshroomEntity; @@ -64,6 +65,7 @@ public final class RequiemEntityShaderPicker implements PickEntityShaderCallback public static final Identifier FISH_EYE_SHADER_ID = shader("fish_eye"); public static final Identifier MOOSHROOM_SHADER_ID = shader("mooshroom"); + public static final Identifier WARDEN_SHADER_ID = shader("warden"); public void registerCallbacks() { PickEntityShaderCallback.EVENT.register(this); @@ -91,6 +93,8 @@ public void pickEntityShader(@Nullable Entity camera, Consumer loadS loadShaderFunc.accept(DOLPHIN_SHADER_ID); } else if (camera instanceof WaterCreatureEntity) { loadShaderFunc.accept(FISH_EYE_SHADER_ID); + } else if (camera instanceof WardenEntity) { + loadShaderFunc.accept(WARDEN_SHADER_ID); } } } diff --git a/src/main/java/ladysnake/requiem/client/particle/SoundParticle.java b/src/main/java/ladysnake/requiem/client/particle/SoundParticle.java new file mode 100644 index 000000000..82d68aac0 --- /dev/null +++ b/src/main/java/ladysnake/requiem/client/particle/SoundParticle.java @@ -0,0 +1,178 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Linking this mod statically or dynamically with second + * modules is making a combined work based on this mod. + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. + * + * In addition, as a special exception, the copyright holders of + * this mod give you permission to combine this mod + * with free software programs or libraries that are released under the GNU LGPL + * and with code included in the standard release of Minecraft under All Rights Reserved (or + * modified versions of such code, with unchanged license). + * You may copy and distribute such a system following the terms of the GNU GPL for this mod + * and the licenses of the second code concerned. + * + * Note that people who make modified versions of this mod are not obligated to grant + * this special exception for their modified versions; it is their choice whether to do so. + * The GNU General Public License gives permission to release a modified version without this exception; + * this exception also makes it possible to release a modified version which carries forward this exception. + */ +package ladysnake.requiem.client.particle; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.VertexConsumer; +import ladysnake.requiem.client.render.RequiemRenderPhases; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.particle.Particle; +import net.minecraft.client.particle.ParticleFactory; +import net.minecraft.client.particle.ParticleTextureSheet; +import net.minecraft.client.particle.SpriteBillboardParticle; +import net.minecraft.client.particle.SpriteProvider; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.particle.DefaultParticleType; +import net.minecraft.util.math.Axis; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.joml.Quaternionf; +import org.joml.Vector3f; +import org.lwjgl.opengl.GL11; +import org.quiltmc.loader.api.minecraft.ClientOnly; + +public class SoundParticle extends SpriteBillboardParticle { + private final SpriteProvider spriteProvider; + + //TODO: by:Redfan2: think about which VertexConsumer to use to not conflict with Darkness fog effect + private static final VertexConsumerProvider.Immediate soundVertexConsumerProvider = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); + + public SoundParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, SpriteProvider spriteProvider) { + super(world, x, y, z, velocityX, velocityY, velocityZ); + this.spriteProvider = spriteProvider; + this.setSpriteForAge(spriteProvider); + + this.maxAge = 10; + this.collidesWithWorld = false; + } + + @Override + public void buildGeometry(VertexConsumer vertexConsumer, Camera camera, float tickDelta) { + if (camera.getFocusedEntity() instanceof PlayerEntity) { + VertexConsumer actualConsumer = soundVertexConsumerProvider.getBuffer(RequiemRenderPhases.GHOST_PARTICLE_LAYER); + + RenderSystem.disableDepthTest(); + RenderSystem.depthFunc(GL11.GL_ALWAYS); + + + Vec3d vec3d = camera.getPos(); + float f = (float) (MathHelper.lerp(tickDelta, this.prevPosX, this.x) - vec3d.getX()); + float g = (float) (MathHelper.lerp(tickDelta, this.prevPosY, this.y) - vec3d.getY()); + float h = (float) (MathHelper.lerp(tickDelta, this.prevPosZ, this.z) - vec3d.getZ()); + Quaternionf quaternion2; + if (this.angle == 0.0F) { + quaternion2 = camera.getRotation(); + } else { + quaternion2 = new Quaternionf(camera.getRotation()); + float i = MathHelper.lerp(tickDelta, this.prevAngle, this.angle); + hamiltonProduct(quaternion2, Axis.Z_POSITIVE.rotation(i)); + } + + Vector3f Vec3f = new Vector3f(-1.0F, -1.0F, 0.0F); + Vec3f.rotate(quaternion2); + Vector3f[] Vec3fs = new Vector3f[]{new Vector3f(-1.0F, -1.0F, 0.0F), new Vector3f(-1.0F, 1.0F, 0.0F), new Vector3f(1.0F, 1.0F, 0.0F), new Vector3f(1.0F, -1.0F, 0.0F)}; + this.getSize(tickDelta); + + for (int k = 0; k < 4; ++k) { + Vector3f Vec3f2 = Vec3fs[k]; + Vec3f2.rotate(quaternion2); + Vec3f2.mul((float) new Vec3d(this.x, this.y, this.z).distanceTo(camera.getPos()) / 10f); + Vec3f2.add(f, g, h); + } + + float minU = this.getMinU(); + float maxU = this.getMaxU(); + float minV = this.getMinV(); + float maxV = this.getMaxV(); + int l = 15728880; + float alpha = 1; + + float red = 1f; + float green = 1f; + float blue = 1f; + actualConsumer.vertex(Vec3fs[0].x(), Vec3fs[0].y(), Vec3fs[0].z()).uv(maxU, maxV).color(red, green, blue, alpha).light(l).next(); + actualConsumer.vertex(Vec3fs[1].x(), Vec3fs[1].y(), Vec3fs[1].z()).uv(maxU, minV).color(red, green, blue, alpha).light(l).next(); + actualConsumer.vertex(Vec3fs[2].x(), Vec3fs[2].y(), Vec3fs[2].z()).uv(minU, minV).color(red, green, blue, alpha).light(l).next(); + actualConsumer.vertex(Vec3fs[3].x(), Vec3fs[3].y(), Vec3fs[3].z()).uv(minU, maxV).color(red, green, blue, alpha).light(l).next(); + + + soundVertexConsumerProvider.draw(); + RenderSystem.enableDepthTest(); + RenderSystem.depthFunc(GL11.GL_LEQUAL); + + } else { + this.markDead(); + } + } + + @Override + public ParticleTextureSheet getType() { + return ParticleTextureSheet.CUSTOM; + } + + public void tick() { + this.setSpriteForAge(spriteProvider); + + if (this.age++ > this.maxAge) { + this.markDead(); + } + + this.prevPosX = this.x; + this.prevPosY = this.y; + this.prevPosZ = this.z; + } + + @ClientOnly + public static class Factory implements ParticleFactory { + private final SpriteProvider spriteProvider; + + public Factory(SpriteProvider spriteProvider) { + this.spriteProvider = spriteProvider; + } + + public Particle createParticle(DefaultParticleType defaultParticleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) { + return new SoundParticle(clientWorld, d, e, f, g, h, i, this.spriteProvider); + } + } + + //Stolen using Linkie + public void hamiltonProduct(Quaternionf first, Quaternionf second) { + float var2 = first.x(); + float var3 = first.y(); + float var4 = first.z(); + float var5 = first.w(); + float var6 = second.x(); + float var7 = second.y(); + float var8 = second.z(); + float var9 = second.w(); + first.x = var5 * var6 + var2 * var9 + var3 * var8 - var4 * var7; + first.y = var5 * var7 - var2 * var8 + var3 * var9 + var4 * var6; + first.z = var5 * var8 + var2 * var7 - var3 * var6 + var4 * var9; + first.w = var5 * var9 - var2 * var6 - var3 * var7 - var4 * var8; + } +} diff --git a/src/main/java/ladysnake/requiem/common/RequiemComponents.java b/src/main/java/ladysnake/requiem/common/RequiemComponents.java index 10efd2dcb..7eb3d46ed 100644 --- a/src/main/java/ladysnake/requiem/common/RequiemComponents.java +++ b/src/main/java/ladysnake/requiem/common/RequiemComponents.java @@ -59,6 +59,7 @@ import ladysnake.requiem.common.entity.cure.SimpleCurableEntityComponent; import ladysnake.requiem.common.entity.effect.PenanceComponent; import ladysnake.requiem.common.entity.effect.StatusEffectReapplicatorImpl; +import ladysnake.requiem.common.entity.warden.WardenSensedComponent; import ladysnake.requiem.common.gamerule.RequiemSyncedGamerules; import ladysnake.requiem.common.possession.LootingPossessedData; import ladysnake.requiem.common.remnant.DroppedVesselTracker; @@ -123,6 +124,7 @@ public void registerEntityComponentFactories(EntityComponentFactoryRegistry regi registry.registerFor(HorseBaseEntity.class, ExternalJumpingMount.KEY, e -> new DummyHorseJumpingMount(e, SoundEvents.ENTITY_HORSE_STEP, getPossessor)); registry.registerForPlayers(RiftTracker.KEY, PlayerRiftTracker::new, RespawnCopyStrategy.ALWAYS_COPY); registry.registerForPlayers(DroppedVesselTracker.KEY, DroppedVesselTracker::new, RespawnCopyStrategy.LOSSLESS_ONLY); + registry.registerForPlayers(WardenSensedComponent.KEY, WardenSensedComponent::new,RespawnCopyStrategy.NEVER_COPY); } @Override diff --git a/src/main/java/ladysnake/requiem/common/entity/internal/WardenExtension.java b/src/main/java/ladysnake/requiem/common/entity/internal/WardenExtension.java new file mode 100644 index 000000000..9e2646d92 --- /dev/null +++ b/src/main/java/ladysnake/requiem/common/entity/internal/WardenExtension.java @@ -0,0 +1,45 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Linking this mod statically or dynamically with other + * modules is making a combined work based on this mod. + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. + * + * In addition, as a special exception, the copyright holders of + * this mod give you permission to combine this mod + * with free software programs or libraries that are released under the GNU LGPL + * and with code included in the standard release of Minecraft under All Rights Reserved (or + * modified versions of such code, with unchanged license). + * You may copy and distribute such a system following the terms of the GNU GPL for this mod + * and the licenses of the other code concerned. + * + * Note that people who make modified versions of this mod are not obligated to grant + * this special exception for their modified versions; it is their choice whether to do so. + * The GNU General Public License gives permission to release a modified version without this exception; + * this exception also makes it possible to release a modified version which carries forward this exception. + */ +package ladysnake.requiem.common.entity.internal; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; + +import java.util.Set; + +public interface WardenExtension { + Set requiem$getVisibleEntities(); + Set requiem$getVisiblePlayers(); +} diff --git a/src/main/java/ladysnake/requiem/common/entity/warden/WardenSensedComponent.java b/src/main/java/ladysnake/requiem/common/entity/warden/WardenSensedComponent.java new file mode 100644 index 000000000..262e62b65 --- /dev/null +++ b/src/main/java/ladysnake/requiem/common/entity/warden/WardenSensedComponent.java @@ -0,0 +1,145 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Linking this mod statically or dynamically with other + * modules is making a combined work based on this mod. + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. + * + * In addition, as a special exception, the copyright holders of + * this mod give you permission to combine this mod + * with free software programs or libraries that are released under the GNU LGPL + * and with code included in the standard release of Minecraft under All Rights Reserved (or + * modified versions of such code, with unchanged license). + * You may copy and distribute such a system following the terms of the GNU GPL for this mod + * and the licenses of the other code concerned. + * + * Note that people who make modified versions of this mod are not obligated to grant + * this special exception for their modified versions; it is their choice whether to do so. + * The GNU General Public License gives permission to release a modified version without this exception; + * this exception also makes it possible to release a modified version which carries forward this exception. + */ +package ladysnake.requiem.common.entity.warden; + +import dev.onyxstudios.cca.api.v3.component.ComponentKey; +import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; +import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; +import dev.onyxstudios.cca.api.v3.entity.PlayerComponent; +import ladysnake.requiem.Requiem; +import ladysnake.requiem.api.v1.possession.PossessionComponent; +import ladysnake.requiem.core.RequiemCore; +import net.minecraft.entity.Entity; +import net.minecraft.entity.mob.warden.WardenEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.server.network.ServerPlayerEntity; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +public class WardenSensedComponent implements PlayerComponent, AutoSyncedComponent { + /*TODO proper implementation of syncing + */ + public static final ComponentKey KEY = ComponentRegistry.getOrCreate(RequiemCore.id("warden_sensed"), WardenSensedComponent.class); + + private Set entities; + + public WardenSensedComponent(PlayerEntity livingEntity) { + this.entities = new HashSet<>(); + } + + public Set getVisible() { + return entities; + } + + @Override + public void readFromNbt(NbtCompound nbt) { + int size = nbt.getInt("list_size"); + if (size > 0) { + Set uuids = new HashSet<>(); + for (int i=0; i < size; i++) { + try { + uuids.add(nbt.getUuid("warden_target_"+i)); + } catch (Exception error) { + Requiem.LOGGER.error("Could not read element {}","warden_target_"+i ); + Requiem.LOGGER.error("Reason: {}", error.getMessage()); + } + } + this.entities = uuids; + } + } + + + @Override + public void writeToNbt(NbtCompound nbt) { + //TODO think about a better data format for this + //MC only seems to have a ByteArray as closest, no UUIDArray or even just StringArray in NBTCompound + nbt.putInt("list_size", entities.size()); + for (int i = 0; i < entities.size(); i++) { + nbt.putUuid( + "warden_target_"+i, + entities.stream().toList().get(i) + ); + } + } + + public WardenSensedComponent setVisibile(Set entities) { + this.entities.addAll(convertToUUID(entities)); + return this; + } + + + @Override + public boolean shouldSyncWith(ServerPlayerEntity player) { + if (PossessionComponent.get(player).isPossessionOngoing() && PossessionComponent.get(player).getHost() instanceof WardenEntity) { + return true; + } else { + return false; + } + } + + public WardenSensedComponent clear() { + this.entities = new HashSet<>(); + return this; + } + + private static Set convertToUUID(Set entities) { + Set idsFromEntities = new HashSet<>(); + entities.forEach(entity -> { + if (entity != null) { + idsFromEntities.add(entity.getUuid()); + } + }); + return idsFromEntities; + } + + public boolean isEmpty() { + return this.entities.isEmpty(); + } + + public boolean isVisibleToWarden(Entity entity) { + return entities.contains(entity.getUuid()); + } + + public void setVisibility(Entity entity, boolean visibile) { + if (visibile && !entities.contains(entity.getUuid())) { + entities.add(entity.getUuid()); + } else { + entities.remove(entity.getUuid()); + } + } +} diff --git a/src/main/java/ladysnake/requiem/common/particle/RequiemParticleTypes.java b/src/main/java/ladysnake/requiem/common/particle/RequiemParticleTypes.java index 1255e59da..9ff21119c 100644 --- a/src/main/java/ladysnake/requiem/common/particle/RequiemParticleTypes.java +++ b/src/main/java/ladysnake/requiem/common/particle/RequiemParticleTypes.java @@ -36,6 +36,7 @@ import com.mojang.serialization.Codec; import ladysnake.requiem.Requiem; +import ladysnake.requiem.client.particle.SoundParticle; import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; import net.minecraft.particle.DefaultParticleType; import net.minecraft.particle.ParticleType; @@ -61,6 +62,7 @@ public Codec getCodec() { }; public static final DefaultParticleType OBELISK_SOUL = FabricParticleTypes.simple(false); public static final DefaultParticleType PENANCE = FabricParticleTypes.simple(false); + public static final DefaultParticleType SOUND = FabricParticleTypes.simple(true); public static void init() { Registry.register(Registries.PARTICLE_TYPE, Requiem.id("attrition"), ATTRITION); @@ -71,5 +73,6 @@ public static void init() { Registry.register(Registries.PARTICLE_TYPE, Requiem.id("soul_trail"), SOUL_TRAIL); Registry.register(Registries.PARTICLE_TYPE, Requiem.id("obelisk_soul"), OBELISK_SOUL); Registry.register(Registries.PARTICLE_TYPE, Requiem.id("penance"), PENANCE); + Registry.register(Registries.PARTICLE_TYPE, Requiem.id("sound"), SOUND); } } diff --git a/src/main/java/ladysnake/requiem/mixin/client/possession/EntityRenderDispatcherMixin.java b/src/main/java/ladysnake/requiem/mixin/client/possession/EntityRenderDispatcherMixin.java index b5130eeee..b7b59cacd 100644 --- a/src/main/java/ladysnake/requiem/mixin/client/possession/EntityRenderDispatcherMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/client/possession/EntityRenderDispatcherMixin.java @@ -37,17 +37,22 @@ import ladysnake.requiem.api.v1.event.requiem.client.RenderSelfPossessedEntityCallback; import ladysnake.requiem.api.v1.possession.PossessionComponent; import ladysnake.requiem.api.v1.remnant.RemnantComponent; +import ladysnake.requiem.common.entity.warden.WardenSensedComponent; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.Camera; import net.minecraft.client.render.Frustum; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; +import net.minecraft.entity.mob.warden.WardenEntity; import net.minecraft.world.World; import net.minecraft.world.WorldView; +import org.spongepowered.asm.mixin.Debug; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -55,11 +60,15 @@ import javax.annotation.Nullable; +@Debug(export=true) @Mixin(EntityRenderDispatcher.class) public abstract class EntityRenderDispatcherMixin { @Shadow public Camera camera; + @Unique @Nullable + /* + The entity the camera belongs to, or the possessed entity*/ private Entity requiem_camerasPossessed; /** @@ -90,4 +99,26 @@ private static void preventShadowRender(MatrixStack matrices, VertexConsumerProv ci.cancel(); } } + + @Inject(method = "shouldRender(Lnet/minecraft/entity/Entity;Lnet/minecraft/client/render/Frustum;DDD)Z", at = @At("HEAD"), cancellable = true) + public void notRenderNonDetectedByWarden(Entity entity, Frustum frustum, double x, double y, double z, CallbackInfoReturnable info) { + + /**/if (entity instanceof WardenEntity) { + info.setReturnValue(true); + } + + ClientPlayerEntity player = MinecraftClient.getInstance().player; + //TODO: by:Redfan2: Fix posessed warden itself not rendering + if (requiem_camerasPossessed != null) { + //Check for posession + if (requiem_camerasPossessed instanceof WardenEntity) { + + if (!player.getComponent(WardenSensedComponent.KEY).isVisibleToWarden(entity)) { + info.setReturnValue(false); + + } + } + } + + } } diff --git a/src/main/java/ladysnake/requiem/mixin/client/possession/nightvision/BackgroundRendererMixin.java b/src/main/java/ladysnake/requiem/mixin/client/possession/nightvision/BackgroundRendererMixin.java index 8e9fe32c8..913375b68 100644 --- a/src/main/java/ladysnake/requiem/mixin/client/possession/nightvision/BackgroundRendererMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/client/possession/nightvision/BackgroundRendererMixin.java @@ -39,6 +39,7 @@ import net.minecraft.client.render.Camera; import net.minecraft.client.world.ClientWorld; import org.objectweb.asm.Opcodes; +import org.quiltmc.loader.api.minecraft.ClientOnly; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -46,6 +47,7 @@ import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +@ClientOnly @Mixin(BackgroundRenderer.class) public abstract class BackgroundRendererMixin { @Shadow diff --git a/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/BackgroundRendererMixin.java b/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/BackgroundRendererMixin.java new file mode 100644 index 000000000..ec025ba03 --- /dev/null +++ b/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/BackgroundRendererMixin.java @@ -0,0 +1,121 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Linking this mod statically or dynamically with other + * modules is making a combined work based on this mod. + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. + * + * In addition, as a special exception, the copyright holders of + * this mod give you permission to combine this mod + * with free software programs or libraries that are released under the GNU LGPL + * and with code included in the standard release of Minecraft under All Rights Reserved (or + * modified versions of such code, with unchanged license). + * You may copy and distribute such a system following the terms of the GNU GPL for this mod + * and the licenses of the other code concerned. + * + * Note that people who make modified versions of this mod are not obligated to grant + * this special exception for their modified versions; it is their choice whether to do so. + * The GNU General Public License gives permission to release a modified version without this exception; + * this exception also makes it possible to release a modified version which carries forward this exception. + */ +package ladysnake.requiem.mixin.client.possession.wardenvision; + +import com.mojang.blaze3d.systems.RenderSystem; +import ladysnake.requiem.api.v1.possession.PossessedData; +import ladysnake.requiem.api.v1.possession.PossessionComponent; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.render.BackgroundRenderer; +import net.minecraft.client.render.Camera; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.mob.warden.WardenEntity; +import net.minecraft.util.math.MathHelper; +import org.quiltmc.loader.api.minecraft.ClientOnly; +import org.spongepowered.asm.mixin.Debug; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Debug(export = true) +@Environment(EnvType.CLIENT) +@Mixin(BackgroundRenderer.class) +public abstract class BackgroundRendererMixin { + + /**The problem: + * I think we should give the Warden the Darkness status effect when he is posessed by a Player. This would also imply us removing the effect after the posession has ended. Can we solve this simpler using a Mixin into the BackgroundRenderer? + * If you know a good way to do this, let me know. I have had a look but couldn't come up with a solution without redirecting "Lnet/minecraft/client/render/BackgroundRenderer$FogEffect;fadeAsEffectWearsOff(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/entity/effect/StatusEffectInstance;FF)F" on line 153 inside render(), + * I am also unsure if it is a good idea to try to emulate the actions that are done on the FogEffect retrieved from the entity, meaning I am unsure if we should set the Fog Distances ourselves + * @see net.minecraft.client.render.BackgroundRenderer#render(Camera, float, ClientWorld, int, float) + * */ + @Unique + private static final StatusEffectInstance EFFECT = new StatusEffectInstance(StatusEffects.DARKNESS,1,1); + + /*@Inject(at = @At("TAIL"), method = "render") + private static void requiem$render(Camera camera, float tickDelta, ClientWorld world, int viewDistance, float skyDarkness, CallbackInfo ci) { + if (camera.getFocusedEntity() instanceof WardenEntity) { + + float factor = 1f; + BackgroundRenderer.FogParameters parameters = new BackgroundRenderer.FogParameters(BackgroundRenderer.FogType.FOG_TERRAIN); + float vark = MathHelper.lerp(factor, viewDistance, 15.0F); + parameters.fogStart = parameters.fogType == BackgroundRenderer.FogType.FOG_SKY ? 0.0F : vark * 0.75F; + parameters.fogEnd = vark; + + RenderSystem.setShaderFogStart(parameters.fogStart); + RenderSystem.setShaderFogEnd(parameters.fogEnd); + RenderSystem.setShaderFogShape(parameters.shape); + } + }*/ + + /**/@Redirect( + at=@At( + value = "INVOKE", + target = "Lnet/minecraft/client/render/BackgroundRenderer$FogEffect;fadeAsEffectWearsOff(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/entity/effect/StatusEffectInstance;FF)F" + ), + method = "render" + ) + private static float requiem$renderWardenDarkness(BackgroundRenderer.FogEffect fogEffect, LivingEntity entity, StatusEffectInstance effect, float horizonShading, float tickDelta) { + if (entity instanceof WardenEntity) { + return fogEffect.fadeAsEffectWearsOff(entity, EFFECT, horizonShading, 0.5f); + } + + return fogEffect.fadeAsEffectWearsOff(entity, entity.getStatusEffect(StatusEffects.DARKNESS), horizonShading, tickDelta); + } + + //This method by itself is useless as it is checked multiple other times whether the entity really has the needed StatusEffect + @Inject(at=@At("HEAD"), method = "findFogEffect(Lnet/minecraft/entity/Entity;F)Lnet/minecraft/client/render/BackgroundRenderer$FogEffect;", cancellable = true) + private static void requiem$findDarknessFogEffect(Entity entity, float tickDelta, CallbackInfoReturnable cir) { + if (entity instanceof WardenEntity) { + + //TODO: by:Redfan2: We do have a AccessWidener for it, why doesn't it work????? + //cir.setReturnValue(new BackgroundRenderer.DarknessFogEffect()); + + //Temporary solution while testing + cir.setReturnValue(BackgroundRenderer.FOG_EFFECTS.stream().filter(BackgroundRenderer.DarknessFogEffect.class::isInstance).toList().get(0)); + + } + } + + +} diff --git a/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/MinecraftClientMixin.java b/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/MinecraftClientMixin.java new file mode 100644 index 000000000..180b23027 --- /dev/null +++ b/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/MinecraftClientMixin.java @@ -0,0 +1,61 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Linking this mod statically or dynamically with other + * modules is making a combined work based on this mod. + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. + * + * In addition, as a special exception, the copyright holders of + * this mod give you permission to combine this mod + * with free software programs or libraries that are released under the GNU LGPL + * and with code included in the standard release of Minecraft under All Rights Reserved (or + * modified versions of such code, with unchanged license). + * You may copy and distribute such a system following the terms of the GNU GPL for this mod + * and the licenses of the other code concerned. + * + * Note that people who make modified versions of this mod are not obligated to grant + * this special exception for their modified versions; it is their choice whether to do so. + * The GNU General Public License gives permission to release a modified version without this exception; + * this exception also makes it possible to release a modified version which carries forward this exception. + */ +package ladysnake.requiem.mixin.client.possession.wardenvision; + +import ladysnake.requiem.common.entity.warden.WardenSensedComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin { + + @Shadow + @Nullable + public ClientPlayerEntity player; + + @Inject(at=@At("HEAD"), method= "hasOutline(Lnet/minecraft/entity/Entity;)Z", cancellable = true) + public void hasOutline(Entity entity, CallbackInfoReturnable cir) { + if (player.getComponent(WardenSensedComponent.KEY).isVisibleToWarden(entity)) { + cir.setReturnValue(true); + } + } +} diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerWorldMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerWorldMixin.java new file mode 100644 index 000000000..d95b6dd3e --- /dev/null +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerWorldMixin.java @@ -0,0 +1,76 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Linking this mod statically or dynamically with other + * modules is making a combined work based on this mod. + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. + * + * In addition, as a special exception, the copyright holders of + * this mod give you permission to combine this mod + * with free software programs or libraries that are released under the GNU LGPL + * and with code included in the standard release of Minecraft under All Rights Reserved (or + * modified versions of such code, with unchanged license). + * You may copy and distribute such a system following the terms of the GNU GPL for this mod + * and the licenses of the other code concerned. + * + * Note that people who make modified versions of this mod are not obligated to grant + * this special exception for their modified versions; it is their choice whether to do so. + * The GNU General Public License gives permission to release a modified version without this exception; + * this exception also makes it possible to release a modified version which carries forward this exception. + */ +package ladysnake.requiem.mixin.common.possession.gameplay; + +import ladysnake.requiem.api.v1.possession.PossessionComponent; +import ladysnake.requiem.common.particle.RequiemParticleTypes; +import net.minecraft.entity.mob.warden.WardenEntity; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; +import net.minecraft.registry.tag.GameEventTags; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.event.GameEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +@Mixin(ServerWorld.class) +public abstract class ServerWorldMixin { + + @Shadow + public abstract boolean sendToPlayerIfNearby(ServerPlayerEntity player, boolean force, double x, double y, double z, Packet packet); + + @Shadow + public abstract List getPlayers(); + + @Inject(method = "emitGameEvent(Lnet/minecraft/world/event/GameEvent;Lnet/minecraft/util/math/Vec3d;Lnet/minecraft/world/event/GameEvent$Context;)V",at=@At("HEAD")) + public void emitGameEvent(GameEvent event, Vec3d pos, GameEvent.Context context, CallbackInfo ci) { + if (event.isIn(GameEventTags.WARDEN_CAN_SENSE)) { + + Packet packet = new ParticleS2CPacket(RequiemParticleTypes.SOUND, true, pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 0, 0, 0, 0, 1); + for (ServerPlayerEntity player : this.getPlayers()) { + if (PossessionComponent.get(player).isPossessionOngoing() && PossessionComponent.getHost(player) instanceof WardenEntity && !(context.sourceEntity() instanceof WardenEntity)) { + this.sendToPlayerIfNearby(player, true, pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, packet); + } + } + } + } +} diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java new file mode 100644 index 000000000..1e76e9fa6 --- /dev/null +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java @@ -0,0 +1,146 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Linking this mod statically or dynamically with other + * modules is making a combined work based on this mod. + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. + * + * In addition, as a special exception, the copyright holders of + * this mod give you permission to combine this mod + * with free software programs or libraries that are released under the GNU LGPL + * and with code included in the standard release of Minecraft under All Rights Reserved (or + * modified versions of such code, with unchanged license). + * You may copy and distribute such a system following the terms of the GNU GPL for this mod + * and the licenses of the other code concerned. + * + * Note that people who make modified versions of this mod are not obligated to grant + * this special exception for their modified versions; it is their choice whether to do so. + * The GNU General Public License gives permission to release a modified version without this exception; + * this exception also makes it possible to release a modified version which carries forward this exception. + */ +package ladysnake.requiem.mixin.common.possession.gameplay; + +import ladysnake.requiem.Requiem; +import ladysnake.requiem.common.entity.internal.WardenExtension; +import ladysnake.requiem.common.entity.warden.WardenSensedComponent; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.mob.HostileEntity; +import net.minecraft.entity.mob.warden.WardenEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import org.quiltmc.loader.api.QuiltLoader; +import org.spongepowered.asm.mixin.Debug; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.HashSet; +import java.util.Set; + +@Debug(export = true) +@Mixin(WardenEntity.class) +public abstract class WardenMixin extends HostileEntity implements WardenExtension { + + @Shadow + public abstract boolean isEnemy(@Nullable Entity entity); + + protected WardenMixin(EntityType entityType, World world) { + super(entityType, world); + } + + + @Unique + @Override + public Set requiem$getVisibleEntities() { + HashSet entities = new java.util.HashSet<>(); + ((WardenEntity)(Object) this).getAngerManager().getSuspects().forEach(entry -> { + if (entry.getSecond() > 0) { + entities.add(((ServerWorld) this.getWorld()).getEntity(entry.getFirst())); + } + }); + + return entities; + } + + @Unique + @Override + public Set requiem$getVisiblePlayers() { + HashSet visiblePlayers = new HashSet<>(); + requiem$getVisibleEntities().forEach(entity->{ + if (entity instanceof PlayerEntity) { + visiblePlayers.add((PlayerEntity) entity); + } + }); + return visiblePlayers; + + } + + @Inject( + method = "mobTick", + at=@At( + target = "Lnet/minecraft/entity/mob/warden/WardenEntity;syncAngerLevel()V", + value= "INVOKE" + ) + ) + public void tickEverySecond(CallbackInfo ci) { + //TODO: by:Redfan2: replace by Mixin + //this.addStatusEffect(new StatusEffectInstance(StatusEffects.DARKNESS,1,0,false,false,false),this); + + + if (age%200==0 ) { + this.requiem$syncSensedEntities(); + if (QuiltLoader.isDevelopmentEnvironment()) { + Requiem.LOGGER.info("Existing Players: {}", requiem$getVisiblePlayers()); + Requiem.LOGGER.info("Existing Entities: {}", requiem$getVisibleEntities().toString()); + } + } + } + + + + + + @Unique + public void requiem$syncSensedEntities() { + if (!this.getWorld().isClient()) { + this.getWorld().getPlayers().forEach(player -> { + if (player.getComponent(WardenSensedComponent.KEY).shouldSyncWith((ServerPlayerEntity) player)){ + player.getComponent(WardenSensedComponent.KEY).setVisibile(requiem$getVisibleEntities()); + WardenSensedComponent.KEY.sync(player); + } + }); + } + } + + + + + @Inject(at=@At("TAIL"),method = "increaseAngerAt(Lnet/minecraft/entity/Entity;IZ)V") + public void syncWhenAngerIncreased(Entity entity, int angerLevel, boolean playSound, CallbackInfo ci) { +if (this.isEnemy(entity)) { + this.requiem$syncSensedEntities(); +} +} + +} diff --git a/src/main/resources/assets/requiem/particles/sound.json b/src/main/resources/assets/requiem/particles/sound.json new file mode 100644 index 000000000..d55ad5d79 --- /dev/null +++ b/src/main/resources/assets/requiem/particles/sound.json @@ -0,0 +1,12 @@ +{ + "textures": [ + "requiem:sound_0", + "requiem:sound_1", + "requiem:sound_2", + "requiem:sound_3", + "requiem:sound_4", + "requiem:sound_5", + "requiem:sound_6", + "requiem:sound_7" + ] +} diff --git a/src/main/resources/assets/requiem/shaders/post/warden.json b/src/main/resources/assets/requiem/shaders/post/warden.json new file mode 100644 index 000000000..9282238fb --- /dev/null +++ b/src/main/resources/assets/requiem/shaders/post/warden.json @@ -0,0 +1,17 @@ +{ + "targets": [ + "swap" + ], + "passes": [ + { + "name": "requiem:warden", + "intarget": "minecraft:main", + "outtarget": "swap" + }, + { + "name": "blit", + "intarget": "swap", + "outtarget": "minecraft:main" + } + ] +} diff --git a/src/main/resources/assets/requiem/shaders/program/warden.fsh b/src/main/resources/assets/requiem/shaders/program/warden.fsh new file mode 100644 index 000000000..e6dab3566 --- /dev/null +++ b/src/main/resources/assets/requiem/shaders/program/warden.fsh @@ -0,0 +1,191 @@ +#version 150 +// Author: @patriciogv - 2015 +// Tittle: Turbulence + +#ifdef GL_ES +precision mediump float; +#endif + +uniform sampler2D DiffuseSampler; + +uniform vec2 OutSize; +uniform float STime; + +in vec2 texCoord; + +out vec4 fragColor; + +// Simplex 3D Noise +// by Ian McEwan, Ashima Arts +// +vec4 permute(vec4 x){ return mod(((x*34.0)+1.0)*x, 289.0); } +vec4 taylorInvSqrt(vec4 r){ return 1.79284291400159 - 0.85373472095314 * r; } + +float snoise(vec3 v){ + const vec2 C = vec2(1.0/6.0, 1.0/3.0); + const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); + + // First corner + vec3 i = floor(v + dot(v, C.yyy)); + vec3 x0 = v - i + dot(i, C.xxx); + + // Other corners + vec3 g = step(x0.yzx, x0.xyz); + vec3 l = 1.0 - g; + vec3 i1 = min(g.xyz, l.zxy); + vec3 i2 = max(g.xyz, l.zxy); + + // x0 = x0 - 0. + 0.0 * C + vec3 x1 = x0 - i1 + 1.0 * C.xxx; + vec3 x2 = x0 - i2 + 2.0 * C.xxx; + vec3 x3 = x0 - 1. + 3.0 * C.xxx; + + // Permutations + i = mod(i, 289.0); + vec4 p = permute(permute(permute( + i.z + vec4(0.0, i1.z, i2.z, 1.0)) + + i.y + vec4(0.0, i1.y, i2.y, 1.0)) + + i.x + vec4(0.0, i1.x, i2.x, 1.0)); + + // Gradients + // ( N*N points uniformly over a square, mapped onto an octahedron.) + float n_ = 1.0/7.0;// N=7 + vec3 ns = n_ * D.wyz - D.xzx; + + vec4 j = p - 49.0 * floor(p * ns.z *ns.z);// mod(p,N*N) + + vec4 x_ = floor(j * ns.z); + vec4 y_ = floor(j - 7.0 * x_);// mod(j,N) + + vec4 x = x_ *ns.x + ns.yyyy; + vec4 y = y_ *ns.x + ns.yyyy; + vec4 h = 1.0 - abs(x) - abs(y); + + vec4 b0 = vec4(x.xy, y.xy); + vec4 b1 = vec4(x.zw, y.zw); + + vec4 s0 = floor(b0)*2.0 + 1.0; + vec4 s1 = floor(b1)*2.0 + 1.0; + vec4 sh = -step(h, vec4(0.0)); + + vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy; + vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww; + + vec3 p0 = vec3(a0.xy, h.x); + vec3 p1 = vec3(a0.zw, h.y); + vec3 p2 = vec3(a1.xy, h.z); + vec3 p3 = vec3(a1.zw, h.w); + + //Normalise gradients + vec4 norm = taylorInvSqrt(vec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0); + m = m * m; + return 42.0 * dot(m*m, vec4(dot(p0, x0), dot(p1, x1), + dot(p2, x2), dot(p3, x3))); +} + +#define OCTAVES 3 +float turbulence (in vec2 st) { + // Initial values + float value = 0.0; + float amplitude = .5; + float frequency = 0.; + // + // Loop of octaves + for (int i = 0; i < OCTAVES; i++) { + value += amplitude * abs(snoise(vec3(st, STime/10.))); + st *= 2.; + amplitude *= .5; + } + return value; +} + +vec3 desaturate(vec3 color, float f) { + vec3 grayXfer = vec3(0.3, 0.59, 0.11); + vec3 gray = vec3(dot(grayXfer, color)); + return mix(color, gray, f); +} + +mat4 brightnessMatrix(float brightness) +{ + return mat4(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + brightness, brightness, brightness, 1); +} + +mat4 contrastMatrix(float contrast) +{ + float t = (1.0 - contrast) / 2.0; + + return mat4(contrast, 0, 0, 0, + 0, contrast, 0, 0, + 0, 0, contrast, 0, + t, t, t, 1); + +} + +mat4 saturationMatrix(float saturation) +{ + vec3 luminance = vec3(0.3086, 0.6094, 0.0820); + + float oneMinusSat = 1.0 - saturation; + + vec3 red = vec3(luminance.x * oneMinusSat); + red+= vec3(saturation, 0, 0); + + vec3 green = vec3(luminance.y * oneMinusSat); + green += vec3(0, saturation, 0); + + vec3 blue = vec3(luminance.z * oneMinusSat); + blue += vec3(0, 0, saturation); + + return mat4(red, 0, + green, 0, + blue, 0, + 0, 0, 0, 1); +} + +void main() { + // vec2 st = gl_FragCoord.xy/OutSize.xy; + // vec3 color = texture(DiffuseSampler, st).rgb; + // st.x *= OutSize.x/OutSize.y; + // + // float t = turbulence(st*5.0); + // color *= 1. - pow(1. - t, 2. /* bigger number = better sight */); + // + // fragColor = vec4(color, 1.0); + + vec2 uv = gl_FragCoord.xy / OutSize.xy; + uv *= 1.0 - uv.yx;//vec2(1.0)- uv.yx; -> 1.-u.yx; Thanks FabriceNeyret ! + float vig = uv.x*uv.y * 50.0;// multiply with sth for intensity + vig = clamp(pow(vig, 0.25), 0., 1.);// change pow for modifying the extend of the vignette + + vec2 st = gl_FragCoord.xy/OutSize.xy; + vec3 color = texture(DiffuseSampler, st).rgb; + + // brighter and desaturated vision + if (!(color.r >= 50./255. && color.r <= 65./255. && color.g >= 205./255. && color.g <= 220./255. && color.b >= 215./255. && color.b <= 230./255.)) { + color *= 3.; + vec3 greyScale = vec3(.5, .5, .5); + color = mix(vec3(dot(color, greyScale)), color, .5); + + st.x *= OutSize.x/OutSize.y; + st = floor(st*100.)/75.; + + float t = turbulence(st*5.); + // float t2 = turbulence(st*10.); + + vec3 overlayColor = t * vec3(0.05, 0.07, 0.09)*5.; + vec3 sculkifiedColor = mix(color, vec3(0.0), clamp(overlayColor.g*10.*(1.-vig), 0., 1.)); + fragColor = vec4(sculkifiedColor, sculkifiedColor); + } else { + fragColor = vec4(color, 1.0); + } +} diff --git a/src/main/resources/assets/requiem/shaders/program/warden.json b/src/main/resources/assets/requiem/shaders/program/warden.json new file mode 100644 index 000000000..208f85def --- /dev/null +++ b/src/main/resources/assets/requiem/shaders/program/warden.json @@ -0,0 +1,59 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "blit", + "fragment": "requiem:warden", + "attributes": [ + "Position" + ], + "samplers": [ + { + "name": "DiffuseSampler" + } + ], + "uniforms": [ + { + "name": "ProjMat", + "type": "matrix4x4", + "count": 16, + "values": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "name": "OutSize", + "type": "float", + "count": 2, + "values": [ + 1.0, + 1.0 + ] + }, + { + "name": "STime", + "type": "float", + "count": 1, + "values": [ + 0.0 + ] + } + ] +} diff --git a/src/main/resources/assets/requiem/textures/particle/sound_0.png b/src/main/resources/assets/requiem/textures/particle/sound_0.png new file mode 100644 index 0000000000000000000000000000000000000000..426613b8cbd71c23c0b1c1cc9d93c7608754ae16 GIT binary patch literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBuf-vKbiP>*~f^wcNjv*HQ$r7xGDAvf ckw-#;Vf8WA`y#s5nn0Bdp00i_>zopr08A(&Gynhq literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/requiem/textures/particle/sound_1.png b/src/main/resources/assets/requiem/textures/particle/sound_1.png new file mode 100644 index 0000000000000000000000000000000000000000..04503273c4c1a8f1e4fea85b6f2083276e6fe7aa GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1enP~FqTF~q_@S%S4$HX^S2gM7=vm`e4HzzYYl{4ULQpeu0v6`K82bfCe#my85}S Ib4q9e0EP@IAOHXW literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/requiem/textures/particle/sound_4.png b/src/main/resources/assets/requiem/textures/particle/sound_4.png new file mode 100644 index 0000000000000000000000000000000000000000..aeb7724e0a0df5fd206ac0639cfc228ef8a775d3 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1en(B0F;F~q_@S>jiNpjR@(>1_Ug&NCAVV!Rob zNAWbQlVsV@naKJ>M98E?BKpEr1INrw2MbP0l+XkK7i2N4 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/requiem/textures/particle/sound_5.png b/src/main/resources/assets/requiem/textures/particle/sound_5.png new file mode 100644 index 0000000000000000000000000000000000000000..31261a00c96981e2f137b10e9f77b84805a00628 GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1enFwoP*F~q_@S)$+o$5O+Fr(4r~MDEM~%v$sIQ89ZJ6T-G@yGywozsy9^t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/requiem/textures/particle/sound_6.png b/src/main/resources/assets/requiem/textures/particle/sound_6.png new file mode 100644 index 0000000000000000000000000000000000000000..9b7f227a32e908a4dba7d3bb0672f0f99e8cd7ea GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1enFxu0_F~q_@d4Y(5QzlPB<=cZ=8p1q%*_thm zGk-98DDO%WIH20c#G%E&G$*U$A`kP4teFc;QX52WCo(K+PZHqt^FcjsqGfs%>iZ#e$5aG$OYG4eCX$;o&V4ClE g Date: Sun, 29 Sep 2024 00:41:07 +0200 Subject: [PATCH 2/4] Remove not working method --- .../wardenvision/BackgroundRendererMixin.java | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/BackgroundRendererMixin.java b/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/BackgroundRendererMixin.java index ec025ba03..610301f14 100644 --- a/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/BackgroundRendererMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/client/possession/wardenvision/BackgroundRendererMixin.java @@ -72,23 +72,8 @@ public abstract class BackgroundRendererMixin { @Unique private static final StatusEffectInstance EFFECT = new StatusEffectInstance(StatusEffects.DARKNESS,1,1); - /*@Inject(at = @At("TAIL"), method = "render") - private static void requiem$render(Camera camera, float tickDelta, ClientWorld world, int viewDistance, float skyDarkness, CallbackInfo ci) { - if (camera.getFocusedEntity() instanceof WardenEntity) { - - float factor = 1f; - BackgroundRenderer.FogParameters parameters = new BackgroundRenderer.FogParameters(BackgroundRenderer.FogType.FOG_TERRAIN); - float vark = MathHelper.lerp(factor, viewDistance, 15.0F); - parameters.fogStart = parameters.fogType == BackgroundRenderer.FogType.FOG_SKY ? 0.0F : vark * 0.75F; - parameters.fogEnd = vark; - - RenderSystem.setShaderFogStart(parameters.fogStart); - RenderSystem.setShaderFogEnd(parameters.fogEnd); - RenderSystem.setShaderFogShape(parameters.shape); - } - }*/ - - /**/@Redirect( + //Some stuff I thought about for potentially solving this + @Redirect( at=@At( value = "INVOKE", target = "Lnet/minecraft/client/render/BackgroundRenderer$FogEffect;fadeAsEffectWearsOff(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/entity/effect/StatusEffectInstance;FF)F" From 662a3fec866419e8efc91170ecf2e423302ffc49 Mon Sep 17 00:00:00 2001 From: Redfan <114088095+Redfan2@users.noreply.github.com> Date: Mon, 30 Sep 2024 19:53:24 +0200 Subject: [PATCH 3/4] Fix Formatting of WardenMixin --- .../common/possession/gameplay/WardenMixin.java | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java index 1e76e9fa6..1c4e56e90 100644 --- a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java @@ -117,10 +117,6 @@ public void tickEverySecond(CallbackInfo ci) { } } - - - - @Unique public void requiem$syncSensedEntities() { if (!this.getWorld().isClient()) { @@ -133,14 +129,10 @@ public void tickEverySecond(CallbackInfo ci) { } } - - - @Inject(at=@At("TAIL"),method = "increaseAngerAt(Lnet/minecraft/entity/Entity;IZ)V") public void syncWhenAngerIncreased(Entity entity, int angerLevel, boolean playSound, CallbackInfo ci) { -if (this.isEnemy(entity)) { - this.requiem$syncSensedEntities(); -} -} - + if (this.isEnemy(entity)) { + this.requiem$syncSensedEntities(); + } + } } From 8025680b4ab3a54f953462816752494c185d79bd Mon Sep 17 00:00:00 2001 From: Redfan <114088095+Redfan2@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:26:31 +0200 Subject: [PATCH 4/4] Bare bones implementation of Colored Sound Particles --- .../client/particle/SoundParticle.java | 51 ++++++---- .../entity/warden/WardenSensedComponent.java | 23 ++--- .../common/particle/RequiemParticleTypes.java | 8 +- .../particle/RequiemSoundParticleEffect.java | 95 ++++++++++++++++++ .../EntityRenderDispatcherMixin.java | 3 +- .../possession/gameplay/ServerWorldMixin.java | 31 +++++- .../possession/gameplay/WardenMixin.java | 25 ++--- .../requiem/textures/particle/sound_0.png | Bin 137 -> 134 bytes .../requiem/textures/particle/sound_1.png | Bin 146 -> 146 bytes .../requiem/textures/particle/sound_2.png | Bin 157 -> 157 bytes .../requiem/textures/particle/sound_3.png | Bin 168 -> 169 bytes .../requiem/textures/particle/sound_4.png | Bin 178 -> 179 bytes .../requiem/textures/particle/sound_5.png | Bin 188 -> 190 bytes .../requiem/textures/particle/sound_6.png | Bin 198 -> 198 bytes .../requiem/textures/particle/sound_7.png | Bin 191 -> 191 bytes .../data/requiem/tags/game_events/blocks.json | 35 +++++++ .../requiem/tags/game_events/entities.json | 28 ++++++ 17 files changed, 245 insertions(+), 54 deletions(-) create mode 100644 src/main/java/ladysnake/requiem/common/particle/RequiemSoundParticleEffect.java create mode 100644 src/main/resources/data/requiem/tags/game_events/blocks.json create mode 100644 src/main/resources/data/requiem/tags/game_events/entities.json diff --git a/src/main/java/ladysnake/requiem/client/particle/SoundParticle.java b/src/main/java/ladysnake/requiem/client/particle/SoundParticle.java index 82d68aac0..0ce2196d9 100644 --- a/src/main/java/ladysnake/requiem/client/particle/SoundParticle.java +++ b/src/main/java/ladysnake/requiem/client/particle/SoundParticle.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * - * Linking this mod statically or dynamically with second + * Linking this mod statically or dynamically with other * modules is making a combined work based on this mod. * Thus, the terms and conditions of the GNU General Public License cover the whole combination. * @@ -25,7 +25,7 @@ * and with code included in the standard release of Minecraft under All Rights Reserved (or * modified versions of such code, with unchanged license). * You may copy and distribute such a system following the terms of the GNU GPL for this mod - * and the licenses of the second code concerned. + * and the licenses of the other code concerned. * * Note that people who make modified versions of this mod are not obligated to grant * this special exception for their modified versions; it is their choice whether to do so. @@ -36,7 +36,9 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.VertexConsumer; +import ladysnake.requiem.api.v1.possession.PossessionComponent; import ladysnake.requiem.client.render.RequiemRenderPhases; +import ladysnake.requiem.common.particle.RequiemSoundParticleEffect; import net.minecraft.client.MinecraftClient; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleFactory; @@ -47,7 +49,6 @@ import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.particle.DefaultParticleType; import net.minecraft.util.math.Axis; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -56,24 +57,38 @@ import org.lwjgl.opengl.GL11; import org.quiltmc.loader.api.minecraft.ClientOnly; -public class SoundParticle extends SpriteBillboardParticle { - private final SpriteProvider spriteProvider; +import java.awt.*; +public class SoundParticle extends SpriteBillboardParticle { + public final SpriteProvider spriteProvider; + private float red; + private float green; + private float blue; + //private final ParticleTextureSheet sheet; //TODO: by:Redfan2: think about which VertexConsumer to use to not conflict with Darkness fog effect - private static final VertexConsumerProvider.Immediate soundVertexConsumerProvider = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); + private static final VertexConsumerProvider.Immediate soundVertexConsumerProvider = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); + //Tessellator.getInstance().getBufferBuilder() + //Doesnt render: Investigate: VertexConsumerProvider.immediate(new BufferBuilder(RequiemRenderPhases.GHOST_PARTICLE_LAYER.getExpectedBufferSize())); - public SoundParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, SpriteProvider spriteProvider) { + public SoundParticle(ClientWorld world, double x, double y, double z, double velocityX, double velocityY, double velocityZ, SpriteProvider spriteProvider, int color) { super(world, x, y, z, velocityX, velocityY, velocityZ); this.spriteProvider = spriteProvider; this.setSpriteForAge(spriteProvider); - + //Testing + Color tempColor = Color.BLUE; + this.green = tempColor.getGreen(); + //this.sheet=new TextureSheet(spriteProvider); + //Tessellator.getInstance().getBufferBuilder(). + this.red = tempColor.getRed(); + this.blue = tempColor.getBlue(); this.maxAge = 10; this.collidesWithWorld = false; } @Override public void buildGeometry(VertexConsumer vertexConsumer, Camera camera, float tickDelta) { - if (camera.getFocusedEntity() instanceof PlayerEntity) { + if (camera.getFocusedEntity() instanceof PlayerEntity player && player.getComponent(PossessionComponent.KEY).isPossessionOngoing()) { + //TODO Disabled for testing if (player.getComponent(PossessionComponent.KEY).getHost() instanceof WardenEntity) { VertexConsumer actualConsumer = soundVertexConsumerProvider.getBuffer(RequiemRenderPhases.GHOST_PARTICLE_LAYER); RenderSystem.disableDepthTest(); @@ -112,9 +127,6 @@ public void buildGeometry(VertexConsumer vertexConsumer, Camera camera, float ti int l = 15728880; float alpha = 1; - float red = 1f; - float green = 1f; - float blue = 1f; actualConsumer.vertex(Vec3fs[0].x(), Vec3fs[0].y(), Vec3fs[0].z()).uv(maxU, maxV).color(red, green, blue, alpha).light(l).next(); actualConsumer.vertex(Vec3fs[1].x(), Vec3fs[1].y(), Vec3fs[1].z()).uv(maxU, minV).color(red, green, blue, alpha).light(l).next(); actualConsumer.vertex(Vec3fs[2].x(), Vec3fs[2].y(), Vec3fs[2].z()).uv(minU, minV).color(red, green, blue, alpha).light(l).next(); @@ -124,7 +136,7 @@ public void buildGeometry(VertexConsumer vertexConsumer, Camera camera, float ti soundVertexConsumerProvider.draw(); RenderSystem.enableDepthTest(); RenderSystem.depthFunc(GL11.GL_LEQUAL); - + //} } else { this.markDead(); } @@ -148,19 +160,20 @@ public void tick() { } @ClientOnly - public static class Factory implements ParticleFactory { - private final SpriteProvider spriteProvider; + public static class Factory implements ParticleFactory { + private final SpriteProvider factorySpriteProvider; public Factory(SpriteProvider spriteProvider) { - this.spriteProvider = spriteProvider; + this.factorySpriteProvider = spriteProvider; } - public Particle createParticle(DefaultParticleType defaultParticleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) { - return new SoundParticle(clientWorld, d, e, f, g, h, i, this.spriteProvider); + @Override + public Particle createParticle(RequiemSoundParticleEffect particleEffect, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) { + return new SoundParticle(clientWorld, d, e, f, g, h, i, this.factorySpriteProvider, particleEffect.getColor()); } } - //Stolen using Linkie + //Stolen using Linkie from Minecraft itself as it doesn't exist on JOML Quaternions public void hamiltonProduct(Quaternionf first, Quaternionf second) { float var2 = first.x(); float var3 = first.y(); diff --git a/src/main/java/ladysnake/requiem/common/entity/warden/WardenSensedComponent.java b/src/main/java/ladysnake/requiem/common/entity/warden/WardenSensedComponent.java index 262e62b65..0c36f3705 100644 --- a/src/main/java/ladysnake/requiem/common/entity/warden/WardenSensedComponent.java +++ b/src/main/java/ladysnake/requiem/common/entity/warden/WardenSensedComponent.java @@ -36,22 +36,22 @@ import dev.onyxstudios.cca.api.v3.component.ComponentKey; import dev.onyxstudios.cca.api.v3.component.ComponentRegistry; +import dev.onyxstudios.cca.api.v3.component.TransientComponent; import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent; -import dev.onyxstudios.cca.api.v3.entity.PlayerComponent; import ladysnake.requiem.Requiem; import ladysnake.requiem.api.v1.possession.PossessionComponent; import ladysnake.requiem.core.RequiemCore; import net.minecraft.entity.Entity; import net.minecraft.entity.mob.warden.WardenEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import java.util.HashSet; import java.util.Set; import java.util.UUID; -public class WardenSensedComponent implements PlayerComponent, AutoSyncedComponent { +public class WardenSensedComponent implements TransientComponent, AutoSyncedComponent { /*TODO proper implementation of syncing */ public static final ComponentKey KEY = ComponentRegistry.getOrCreate(RequiemCore.id("warden_sensed"), WardenSensedComponent.class); @@ -67,13 +67,13 @@ public Set getVisible() { } @Override - public void readFromNbt(NbtCompound nbt) { - int size = nbt.getInt("list_size"); + public void applySyncPacket(PacketByteBuf buf) { + int size = buf.readInt(); if (size > 0) { Set uuids = new HashSet<>(); for (int i=0; i < size; i++) { try { - uuids.add(nbt.getUuid("warden_target_"+i)); + uuids.add(buf.readUuid()); } catch (Exception error) { Requiem.LOGGER.error("Could not read element {}","warden_target_"+i ); Requiem.LOGGER.error("Reason: {}", error.getMessage()); @@ -83,17 +83,14 @@ public void readFromNbt(NbtCompound nbt) { } } - @Override - public void writeToNbt(NbtCompound nbt) { + public void writeSyncPacket(PacketByteBuf buf, ServerPlayerEntity recipient) { + //TODO think about a better data format for this //MC only seems to have a ByteArray as closest, no UUIDArray or even just StringArray in NBTCompound - nbt.putInt("list_size", entities.size()); + buf.writeInt(entities.size()); for (int i = 0; i < entities.size(); i++) { - nbt.putUuid( - "warden_target_"+i, - entities.stream().toList().get(i) - ); + buf.writeUuid(entities.stream().toList().get(i)); } } diff --git a/src/main/java/ladysnake/requiem/common/particle/RequiemParticleTypes.java b/src/main/java/ladysnake/requiem/common/particle/RequiemParticleTypes.java index 9ff21119c..7127b5859 100644 --- a/src/main/java/ladysnake/requiem/common/particle/RequiemParticleTypes.java +++ b/src/main/java/ladysnake/requiem/common/particle/RequiemParticleTypes.java @@ -36,7 +36,6 @@ import com.mojang.serialization.Codec; import ladysnake.requiem.Requiem; -import ladysnake.requiem.client.particle.SoundParticle; import net.fabricmc.fabric.api.particle.v1.FabricParticleTypes; import net.minecraft.particle.DefaultParticleType; import net.minecraft.particle.ParticleType; @@ -62,7 +61,12 @@ public Codec getCodec() { }; public static final DefaultParticleType OBELISK_SOUL = FabricParticleTypes.simple(false); public static final DefaultParticleType PENANCE = FabricParticleTypes.simple(false); - public static final DefaultParticleType SOUND = FabricParticleTypes.simple(true); + public static final ParticleType SOUND = new ParticleType<>(false, RequiemSoundParticleEffect.PARAMETERS_FACTORY) { + @Override + public Codec getCodec() { + return RequiemSoundParticleEffect.codec(this); + } + }; public static void init() { Registry.register(Registries.PARTICLE_TYPE, Requiem.id("attrition"), ATTRITION); diff --git a/src/main/java/ladysnake/requiem/common/particle/RequiemSoundParticleEffect.java b/src/main/java/ladysnake/requiem/common/particle/RequiemSoundParticleEffect.java new file mode 100644 index 000000000..b6ca85032 --- /dev/null +++ b/src/main/java/ladysnake/requiem/common/particle/RequiemSoundParticleEffect.java @@ -0,0 +1,95 @@ +/* + * Requiem + * Copyright (C) 2017-2024 Ladysnake + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Linking this mod statically or dynamically with other + * modules is making a combined work based on this mod. + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. + * + * In addition, as a special exception, the copyright holders of + * this mod give you permission to combine this mod + * with free software programs or libraries that are released under the GNU LGPL + * and with code included in the standard release of Minecraft under All Rights Reserved (or + * modified versions of such code, with unchanged license). + * You may copy and distribute such a system following the terms of the GNU GPL for this mod + * and the licenses of the other code concerned. + * + * Note that people who make modified versions of this mod are not obligated to grant + * this special exception for their modified versions; it is their choice whether to do so. + * The GNU General Public License gives permission to release a modified version without this exception; + * this exception also makes it possible to release a modified version which carries forward this exception. + */ +package ladysnake.requiem.common.particle; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.particle.ParticleEffect; +import net.minecraft.particle.ParticleType; +import net.minecraft.registry.Registries; + + +public class RequiemSoundParticleEffect implements ParticleEffect { + public RequiemSoundParticleEffect(ParticleType type, int color) { + this.type = type; + this.color = color; + } + + public int color; + private final ParticleType type; + + + public static final Factory PARAMETERS_FACTORY = new Factory<>() { + @Override + public RequiemSoundParticleEffect read(ParticleType particleType, StringReader stringReader) throws CommandSyntaxException { + stringReader.expect(' '); + int color = stringReader.readInt(); + return new RequiemSoundParticleEffect(particleType, color); + } + + @Override + public RequiemSoundParticleEffect read(ParticleType particleType, PacketByteBuf buf) { + return new RequiemSoundParticleEffect(particleType, buf.readInt()); + } + }; + + @Override + public void write(PacketByteBuf buf) { + buf.writeInt(color); + } + + @Override + public String asString() { + return "%s %d".formatted(Registries.PARTICLE_TYPE.getId(this.getType()), this.color); + } + + @Override + public ParticleType getType() { + return this.type; + } + + public int getColor() { + return this.color; + } + + public static Codec codec(ParticleType particleType) { + return RecordCodecBuilder.create(instance -> instance.group( + Codec.INT.fieldOf("color").forGetter(RequiemSoundParticleEffect::getColor) + ).apply(instance, color -> new RequiemSoundParticleEffect(particleType, color))); + } +} diff --git a/src/main/java/ladysnake/requiem/mixin/client/possession/EntityRenderDispatcherMixin.java b/src/main/java/ladysnake/requiem/mixin/client/possession/EntityRenderDispatcherMixin.java index b7b59cacd..7ac79d835 100644 --- a/src/main/java/ladysnake/requiem/mixin/client/possession/EntityRenderDispatcherMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/client/possession/EntityRenderDispatcherMixin.java @@ -104,11 +104,12 @@ private static void preventShadowRender(MatrixStack matrices, VertexConsumerProv public void notRenderNonDetectedByWarden(Entity entity, Frustum frustum, double x, double y, double z, CallbackInfoReturnable info) { /**/if (entity instanceof WardenEntity) { + //TODO: by:Redfan2: Fix posessed warden itself not rendering info.setReturnValue(true); } ClientPlayerEntity player = MinecraftClient.getInstance().player; - //TODO: by:Redfan2: Fix posessed warden itself not rendering + if (requiem_camerasPossessed != null) { //Check for posession if (requiem_camerasPossessed instanceof WardenEntity) { diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerWorldMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerWorldMixin.java index d95b6dd3e..a6e4603f9 100644 --- a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerWorldMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/ServerWorldMixin.java @@ -34,14 +34,19 @@ */ package ladysnake.requiem.mixin.common.possession.gameplay; +import ladysnake.requiem.Requiem; import ladysnake.requiem.api.v1.possession.PossessionComponent; import ladysnake.requiem.common.particle.RequiemParticleTypes; +import ladysnake.requiem.common.particle.RequiemSoundParticleEffect; import net.minecraft.entity.mob.warden.WardenEntity; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; +import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.tag.GameEventTags; +import net.minecraft.registry.tag.TagKey; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; import net.minecraft.util.math.Vec3d; import net.minecraft.world.event.GameEvent; import org.spongepowered.asm.mixin.Mixin; @@ -50,6 +55,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.awt.*; import java.util.List; @Mixin(ServerWorld.class) @@ -64,11 +70,32 @@ public abstract class ServerWorldMixin { @Inject(method = "emitGameEvent(Lnet/minecraft/world/event/GameEvent;Lnet/minecraft/util/math/Vec3d;Lnet/minecraft/world/event/GameEvent$Context;)V",at=@At("HEAD")) public void emitGameEvent(GameEvent event, Vec3d pos, GameEvent.Context context, CallbackInfo ci) { if (event.isIn(GameEventTags.WARDEN_CAN_SENSE)) { + //TODO: by:Redfan2: maybe ask Tags for Color - Packet packet = new ParticleS2CPacket(RequiemParticleTypes.SOUND, true, pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 0, 0, 0, 0, 1); + //Fallback + Color color = Color.white; + + if (event.isIn(TagKey.of(RegistryKeys.GAME_EVENT, new Identifier(Requiem.MOD_ID,"blocks")))) { + color = Color.green; + } + if (event.isIn(TagKey.of(RegistryKeys.GAME_EVENT,new Identifier(Requiem.MOD_ID,"entities")))) { + color = Color.cyan; + } + Packet packet = new ParticleS2CPacket( + new RequiemSoundParticleEffect(RequiemParticleTypes.SOUND, color.getRGB()), + true, + pos.getX() + .5f, + pos.getY() + .5f, + pos.getZ() + .5f, + 0, + 0, + 0, + 0, + 1 + ); for (ServerPlayerEntity player : this.getPlayers()) { if (PossessionComponent.get(player).isPossessionOngoing() && PossessionComponent.getHost(player) instanceof WardenEntity && !(context.sourceEntity() instanceof WardenEntity)) { - this.sendToPlayerIfNearby(player, true, pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, packet); + this.sendToPlayerIfNearby(player, true, pos.getX(), pos.getY(), pos.getZ(), packet); } } } diff --git a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java index 1c4e56e90..f505963e8 100644 --- a/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java +++ b/src/main/java/ladysnake/requiem/mixin/common/possession/gameplay/WardenMixin.java @@ -34,11 +34,12 @@ */ package ladysnake.requiem.mixin.common.possession.gameplay; -import ladysnake.requiem.Requiem; import ladysnake.requiem.common.entity.internal.WardenExtension; import ladysnake.requiem.common.entity.warden.WardenSensedComponent; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.mob.warden.WardenEntity; import net.minecraft.entity.player.PlayerEntity; @@ -46,8 +47,6 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; -import org.quiltmc.loader.api.QuiltLoader; -import org.spongepowered.asm.mixin.Debug; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -58,7 +57,6 @@ import java.util.HashSet; import java.util.Set; -@Debug(export = true) @Mixin(WardenEntity.class) public abstract class WardenMixin extends HostileEntity implements WardenExtension { @@ -99,22 +97,15 @@ protected WardenMixin(EntityType entityType, World worl @Inject( method = "mobTick", at=@At( - target = "Lnet/minecraft/entity/mob/warden/WardenEntity;syncAngerLevel()V", - value= "INVOKE" + value= "TAIL" ) ) public void tickEverySecond(CallbackInfo ci) { - //TODO: by:Redfan2: replace by Mixin - //this.addStatusEffect(new StatusEffectInstance(StatusEffects.DARKNESS,1,0,false,false,false),this); - - - if (age%200==0 ) { - this.requiem$syncSensedEntities(); - if (QuiltLoader.isDevelopmentEnvironment()) { - Requiem.LOGGER.info("Existing Players: {}", requiem$getVisiblePlayers()); - Requiem.LOGGER.info("Existing Entities: {}", requiem$getVisibleEntities().toString()); - } - } + //TODO: by:Redfan2: replace by Mixin + this.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS,-1,5,false,false,false),this); + if (age % 200 == 0 ) { + this.requiem$syncSensedEntities(); + } } @Unique diff --git a/src/main/resources/assets/requiem/textures/particle/sound_0.png b/src/main/resources/assets/requiem/textures/particle/sound_0.png index 426613b8cbd71c23c0b1c1cc9d93c7608754ae16..9ed8a2775b12a191c731ef53623bae028a316b66 100644 GIT binary patch delta 68 zcmeBVY-60@X?uWyf$sog*0oMf1_lOcPZ!4!3;$#Z*28jt+L<)OwG)~yElyBjW@BTp XzRmu7@^QU`KxGV`u6{1-oD!M|~ta>2Q#Nf$t#Wj)~cC85kJkJY5_^Ec}xtSP#oZ#8rQgZ&?_#rh(I|ziA?m bgapItW32Z@bgeakDj7Uo{an^LB{Ts5Ip`LT diff --git a/src/main/resources/assets/requiem/textures/particle/sound_1.png b/src/main/resources/assets/requiem/textures/particle/sound_1.png index 04503273c4c1a8f1e4fea85b6f2083276e6fe7aa..ea0f9e8fb2c789941afef6e2489a15223e75766b 100644 GIT binary patch delta 80 zcmbQlIEitBr{_Ti2EK!gJ0@noWnf@X_jGX#vG7lpU~QKD)6S$Z-K1fS;Cw}&fLUe? kDaITQI~ONRU}9rqm}@Qm`qu8qBA^xqPgg&ebxsLQ01I;&u>b%7 delta 80 zcmbQlIEitBr{^IC2EId#q8eTe3=9nFo-U3d7XHZ+tj)3!an&E>TNcJ#V%X$X(`Mk9 kd5fWIj{(;UHVFxaGBd&H|GlPN0cv6JboFyt=akR{0NS}3s{jB1 diff --git a/src/main/resources/assets/requiem/textures/particle/sound_2.png b/src/main/resources/assets/requiem/textures/particle/sound_2.png index 89911d5e3edd4bdb4d758bfb316964dc7f402f57..c4010d2ad233e649ee281e14b685a76bab455828 100644 GIT binary patch delta 91 zcmV-h0Hpt&0i6MmNmRiA01m+cxRGn^0000oNkl*SS0#NQKpbcPP0091*C)>s<=Cc3*002ovPDHLkV1i|Y9{vCT delta 91 zcmV-h0Hpt&0i6MmNmRlB01mZ xL$GPUWe5|Lraqv^3oroENVeutKrCQj002Oy9Zz|Za2o&s002ovPDHLkV1gtG9bfcw zX)}YF;TnedPB}$B0kd)pKCmUQ-uTny%fpf(+^fuGV8Fnj;3)qwI?wYb&?E*=S3j3^ HP6pt0AD!ZlS2X66ynlMn}jr!00RR6fuS$q TYuu2+00000NkvXXu0mjfp718< delta 112 zcmV-$0FVE(0kQ#*Nom3W01m_!JT}gcw`U)i6P6vcbR`fB`59L>R!P5SM1!B&4AP7#IK;!6j8Y Ss#Svk0000*~g2tXMjv*Ss$q6pZJ6I$d7)~(>pHLBLX6$L!V|aeJB85Z2 pB|(OVk*B>;BV@TUvk9Y{8$*Qv!^6sdW@bR`44$rjF6*2UngHF_DaQZ+ delta 142 zcmdnTxQB6qBnKM<1B3kM|A`Y76{Fr%o3R|8No(9^{+#KJ#WqTm3> zQp1L)TiO3F^f9nlx3nQxmy03O)JTIg84c&%Cb$k8uX^A(VT&m tCr9T1!wI$=y@RTLf0y{AA2`6kkYQse_;&uYw?M-gJYD@<);T3K0RWkJFcSa( diff --git a/src/main/resources/assets/requiem/textures/particle/sound_6.png b/src/main/resources/assets/requiem/textures/particle/sound_6.png index 9b7f227a32e908a4dba7d3bb0672f0f99e8cd7ea..c3ad62e385713a2356d148f5bda50a8bfc62b823 100644 GIT binary patch delta 70 zcmX@cc#Ls^r}{w#2EK!gJ0@noWnf^4_H=O!vG7k`AY$N@$@Ag=|No%@Y7z!UMr{)d aoJ0;ZdY*n`^i2||kipZ{&t;ucLK6UlRvCBz delta 70 zcmX@cc#Ls^r}`lV2EId#q8eTe3=9m>o-U3d7XHZ#L=2oVc@iq$9@Nqh=IP7UY?)Z# ZB(k90?EI=_5-~u944$rjF6*2UngH^p76JeO diff --git a/src/main/resources/assets/requiem/textures/particle/sound_7.png b/src/main/resources/assets/requiem/textures/particle/sound_7.png index 01587d5b7249ea993b4764aed578b1070e9f0ae9..f068538ba716008c7b47ffe76e38e6fe29a027ac 100644 GIT binary patch delta 66 zcmdnbxSw%?r}9At2EK!gJ0@noWnf?k@pN$vvG7k$Il%Pq|9^R|)I|(#ZpS9(*o*v* WbH4gkIO+;e5re0zpUXO@geCwmW*C$J delta 66 zcmdnbxSw%?r}7~N2EId#q8eTe3=9k*o-U3d7XHa82bgr$+j6uT1s*8WZJn57FXEVC VaC6dGp@Tq044$rjF6*2UngE=56wUwu diff --git a/src/main/resources/data/requiem/tags/game_events/blocks.json b/src/main/resources/data/requiem/tags/game_events/blocks.json new file mode 100644 index 000000000..67057b923 --- /dev/null +++ b/src/main/resources/data/requiem/tags/game_events/blocks.json @@ -0,0 +1,35 @@ +{ + "values": [ + "minecraft:block_attach", + "minecraft:block_change", + "minecraft:block_close", + "minecraft:block_destroy", + "minecraft:block_detach", + "minecraft:block_open", + "minecraft:block_place", + "minecraft:block_activate", + "minecraft:block_deactivate", + "minecraft:container_close", + "minecraft:container_open", + "minecraft:explode", + "minecraft:fluid_pickup", + "minecraft:fluid_place", + "minecraft:note_block_play", + "minecraft:resonate_1", + "minecraft:resonate_2", + "minecraft:resonate_3", + "minecraft:resonate_4", + "minecraft:resonate_5", + "minecraft:resonate_6", + "minecraft:resonate_7", + "minecraft:resonate_8", + "minecraft:resonate_9", + "minecraft:resonate_10", + "minecraft:resonate_11", + "minecraft:resonate_12", + "minecraft:resonate_13", + "minecraft:resonate_14", + "minecraft:resonate_15", + "minecraft:shriek" + ] +} diff --git a/src/main/resources/data/requiem/tags/game_events/entities.json b/src/main/resources/data/requiem/tags/game_events/entities.json new file mode 100644 index 000000000..a43bf0b30 --- /dev/null +++ b/src/main/resources/data/requiem/tags/game_events/entities.json @@ -0,0 +1,28 @@ +{ + "values": [ + "minecraft:drink", + "minecraft:eat", + "minecraft:elytra_glide", + "minecraft:entity_damage", + "minecraft:entity_die", + "minecraft:entity_dismount", + "minecraft:entity_interact", + "minecraft:entity_mount", + "minecraft:entity_place", + "minecraft:entity_roar", + "minecraft:entity_shake", + "minecraft:equip", + "minecraft:hit_ground", + "minecraft:instrument_play", + "minecraft:item_interact_finish", + "minecraft:lightning_strike", + "minecraft:prime_fuse", + "minecraft:projectile_land", + "minecraft:projectile_shoot", + "minecraft:shear", + "minecraft:splash", + "minecraft:step", + "minecraft:swim", + "minecraft:teleport" + ] +}