Skip to content

Commit

Permalink
Merge branch '1.21' into 1.21.3
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/java/eu/ha3/presencefootsteps/sound/generator/TerrestrialStepSoundGenerator.java
  • Loading branch information
Sollace committed Dec 12, 2024
2 parents ce4c732 + 0a8db26 commit f3e93b0
Show file tree
Hide file tree
Showing 19 changed files with 555 additions and 78 deletions.
7 changes: 6 additions & 1 deletion src/main/java/eu/ha3/presencefootsteps/sound/Isolator.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import eu.ha3.presencefootsteps.util.JsonObjectWriter;
import eu.ha3.presencefootsteps.util.ResourceUtils;
import eu.ha3.presencefootsteps.util.BlockReport.Reportable;
import eu.ha3.presencefootsteps.world.BiomeVarianceLookup;
import eu.ha3.presencefootsteps.world.GolemLookup;
import eu.ha3.presencefootsteps.world.HeuristicStateLookup;
import eu.ha3.presencefootsteps.world.Index;
Expand All @@ -34,10 +35,12 @@ public record Isolator (
HeuristicStateLookup heuristics,
Lookup<EntityType<?>> golems,
Lookup<BlockState> blocks,
Index<Identifier, BiomeVarianceLookup.BiomeVariance> biomes,
Lookup<SoundEvent> primitives,
AcousticLibrary acoustics
) implements Reportable {
private static final Identifier BLOCK_MAP = PresenceFootsteps.id("config/blockmap.json");
private static final Identifier BIOME_MAP = PresenceFootsteps.id("config/biomevariancemap.json");
private static final Identifier GOLEM_MAP = PresenceFootsteps.id("config/golemmap.json");
private static final Identifier LOCOMOTION_MAP = PresenceFootsteps.id("config/locomotionmap.json");
private static final Identifier PRIMITIVE_MAP = PresenceFootsteps.id("config/primitivemap.json");
Expand All @@ -50,14 +53,16 @@ public Isolator(SoundEngine engine) {
new HeuristicStateLookup(),
new GolemLookup(),
new StateLookup(),
new BiomeVarianceLookup(),
new PrimitiveLookup(),
new AcousticsPlayer(new DelayedSoundPlayer(engine.soundPlayer))
);
}

public boolean load(ResourceManager manager) {
boolean hasConfigurations = false;
hasConfigurations |= ResourceUtils.forEachReverse(BLOCK_MAP, manager, blocks()::load);
hasConfigurations |= ResourceUtils.forEach(BLOCK_MAP, manager, blocks()::load);
hasConfigurations |= ResourceUtils.forEach(BIOME_MAP, manager, biomes()::load);
hasConfigurations |= ResourceUtils.forEach(GOLEM_MAP, manager, golems()::load);
hasConfigurations |= ResourceUtils.forEach(PRIMITIVE_MAP, manager, primitives()::load);
hasConfigurations |= ResourceUtils.forEach(LOCOMOTION_MAP, manager, locomotions()::load);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
* @author Hurry
*/
public interface StepSoundGenerator {

float getLocalPitch(float tickDelta);

float getLocalVolume(float tickDelta);

/**
* Gets the motion tracker used to determine the direction and speed for an entity during simulation.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.passive.AbstractHorseEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.tag.FluidTags;
import net.minecraft.util.math.BlockPos;
import org.jetbrains.annotations.Nullable;
Expand All @@ -15,11 +16,13 @@
import eu.ha3.presencefootsteps.config.Variator;
import eu.ha3.presencefootsteps.mixins.ILivingEntity;
import eu.ha3.presencefootsteps.sound.State;
import eu.ha3.presencefootsteps.util.Lerp;
import eu.ha3.presencefootsteps.util.PlayerUtil;
import eu.ha3.presencefootsteps.sound.Options;
import eu.ha3.presencefootsteps.sound.SoundEngine;
import eu.ha3.presencefootsteps.world.Association;
import eu.ha3.presencefootsteps.world.AssociationPool;
import eu.ha3.presencefootsteps.world.BiomeVarianceLookup;
import eu.ha3.presencefootsteps.world.Solver;
import eu.ha3.presencefootsteps.world.SoundsKey;
import eu.ha3.presencefootsteps.world.Substrates;
Expand Down Expand Up @@ -58,20 +61,40 @@ class TerrestrialStepSoundGenerator implements StepSoundGenerator {
protected final MotionTracker motionTracker = new MotionTracker(this);
protected final AssociationPool associations;

private final Lerp biomePitch = new Lerp();
private final Lerp biomeVolume = new Lerp();

public TerrestrialStepSoundGenerator(LivingEntity entity, SoundEngine engine, Modifier<TerrestrialStepSoundGenerator> modifier) {
this.entity = entity;
this.engine = engine;
this.modifier = modifier;
this.associations = new AssociationPool(entity, engine);
}

@Override
public float getLocalPitch(float tickDelta) {
return biomePitch.get(tickDelta);
}

@Override
public float getLocalVolume(float tickDelta) {
return biomeVolume.get(tickDelta);
}

@Override
public MotionTracker getMotionTracker() {
return motionTracker;
}

@Override
public void generateFootsteps() {
BiomeVarianceLookup.BiomeVariance variance = entity.getWorld().getBiome(entity.getBlockPos()).getKey().map(RegistryKey::getValue).map(key -> {
return engine.getIsolator().biomes().lookup(key);
}).orElse(BiomeVarianceLookup.BiomeVariance.DEFAULT);

biomePitch.update(variance.pitch(), 0.01F);
biomeVolume.update(variance.volume(), 0.01F);

motionTracker.simulateMotionData(entity);
simulateFootsteps();
simulateAirborne();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import eu.ha3.presencefootsteps.util.PlayerUtil;
import eu.ha3.presencefootsteps.sound.Options;
import eu.ha3.presencefootsteps.sound.SoundEngine;
import eu.ha3.presencefootsteps.sound.StepSoundSource;
import eu.ha3.presencefootsteps.sound.generator.StepSoundGenerator;

/**
* A Library that can also play sounds and default footsteps.
Expand Down Expand Up @@ -41,6 +43,13 @@ public void playSound(LivingEntity location, String soundName, float volume, flo
volume *= engine.getVolumeForSource(location);
pitch /= ((PlayerUtil.getScale(location) - 1) * 0.6F) + 1;

StepSoundGenerator generator = ((StepSoundSource) location).getStepGenerator(engine).orElse(null);
if (generator != null) {
float tickDelta = mc.getRenderTickCounter().getTickDelta(false);
volume *= generator.getLocalVolume(tickDelta);
pitch *= generator.getLocalPitch(tickDelta);
}

PositionedSoundInstance sound = new UncappedSoundInstance(soundName, volume, pitch, location);

if (distance > 100) {
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/eu/ha3/presencefootsteps/util/Lerp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package eu.ha3.presencefootsteps.util;

import net.minecraft.util.math.MathHelper;

public class Lerp {
public float previous;
public float current;

public void update(float newTarget, float rate) {
previous = current;
if (current < newTarget) {
current = Math.min(current + rate, newTarget);
}
if (current > newTarget) {
current = Math.max(current - rate, newTarget);
}
}

public float get(float tickDelta) {
return MathHelper.lerp(tickDelta, previous, current);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import org.jetbrains.annotations.Nullable;

import com.google.gson.JsonElement;

import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import net.minecraft.util.Identifier;

Expand Down Expand Up @@ -46,14 +48,14 @@ public Set<String> getSubstrates() {
}

@Override
public void add(String key, String value) {
public void add(String key, JsonElement value) {
final String[] split = key.trim().split("@");
final String primitive = split[0];
final String substrate = split.length > 1 ? split[1] : Substrates.DEFAULT;

substrates
.computeIfAbsent(substrate, s -> new Object2ObjectLinkedOpenHashMap<>())
.put(Identifier.of(primitive), SoundsKey.of(value));
.put(Identifier.of(primitive), SoundsKey.of(value.getAsString()));
}

@Override
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/eu/ha3/presencefootsteps/world/Association.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,27 @@ public record Association (
BlockState state,
BlockPos pos,
@Nullable LivingEntity source,
boolean forcePlay,

SoundsKey dry,
SoundsKey wet,
SoundsKey foliage
) {
public static final Association NOT_EMITTER = new Association(Blocks.AIR.getDefaultState(), BlockPos.ORIGIN, null, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
public static final Association NOT_EMITTER = new Association(Blocks.AIR.getDefaultState(), BlockPos.ORIGIN, null, false, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);

public static Association of(BlockState state, BlockPos pos, LivingEntity source, SoundsKey dry, SoundsKey wet, SoundsKey foliage) {
public static Association of(BlockState state, BlockPos pos, LivingEntity source, boolean forcePlay, SoundsKey dry, SoundsKey wet, SoundsKey foliage) {
if (dry.isSilent() && wet.isSilent() && foliage.isSilent()) {
return NOT_EMITTER;
}
return new Association(state, pos.toImmutable(), source, dry, wet, foliage);
return new Association(state, pos.toImmutable(), source, forcePlay, dry, wet, foliage);
}

public boolean isResult() {
return dry.isResult() || wet.isResult() || foliage.isResult();
}

public boolean isSilent() {
return this == NOT_EMITTER || state.isAir();
return this == NOT_EMITTER || (state.isAir() && !forcePlay);
}

public boolean dataEquals(Association other) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public SoundsKey get(BlockPos pos, BlockState state, String substrate) {
return !e.isCollidable() || e.getBoundingBox().maxY < entity.getY() + 0.2F;
})) {
if ((association = engine.getIsolator().golems().getAssociation(golem.getType(), substrate)).isEmitter()) {
wasGolem = true;
return association;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package eu.ha3.presencefootsteps.world;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.google.gson.JsonElement;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;

import eu.ha3.presencefootsteps.util.JsonObjectWriter;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.util.Identifier;

public class BiomeVarianceLookup implements Index<Identifier, BiomeVarianceLookup.BiomeVariance> {
private final Map<Identifier, BiomeVariance> entries = new HashMap<>();

@Override
public BiomeVariance lookup(Identifier key) {
return entries.getOrDefault(key, BiomeVariance.DEFAULT);
}

@Override
public boolean contains(Identifier key) {
return entries.containsKey(key);
}

@Override
public void add(String key, JsonElement value) {
BiomeVariance.CODEC.decode(JsonOps.INSTANCE, value).result().map(Pair::getFirst).ifPresent(i -> {
entries.put(Identifier.of(key), i);
});
}

@Override
public void writeToReport(boolean full, JsonObjectWriter writer, Map<String, BlockSoundGroup> groups) throws IOException {
}

public record BiomeVariance(float volume, float pitch) {
public static final BiomeVariance DEFAULT = new BiomeVariance(1, 1);
static final Codec<BiomeVariance> CODEC = RecordCodecBuilder.create(i -> i.group(
Codec.FLOAT.fieldOf("volume").forGetter(BiomeVariance::volume),
Codec.FLOAT.fieldOf("pitch").forGetter(BiomeVariance::pitch)
).apply(i, BiomeVariance::new));
}
}
5 changes: 3 additions & 2 deletions src/main/java/eu/ha3/presencefootsteps/world/Loadable.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.Reader;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

public interface Loadable {
Expand All @@ -11,7 +12,7 @@ public interface Loadable {
/**
* Register a blockmap entry.
*/
void add(String key, String value);
void add(String key, JsonElement json);

/**
* Loads new entries from the given config reader.
Expand All @@ -21,7 +22,7 @@ default void load(Reader reader) {
JsonObject json = GSON.fromJson(reader, JsonObject.class);

json.entrySet().forEach(entry -> {
add(entry.getKey(), entry.getValue().getAsString());
add(entry.getKey(), entry.getValue());
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.io.IOException;
import java.util.Map;

import com.google.gson.JsonElement;

public class LocomotionLookup implements Index<Entity, Locomotion> {
private final Map<Identifier, Locomotion> values = new Object2ObjectLinkedOpenHashMap<>();

Expand All @@ -36,14 +38,14 @@ public Locomotion lookup(Entity key) {
}

@Override
public void add(String key, String value) {
public void add(String key, JsonElement value) {
Identifier id = Identifier.of(key);

if (!Registries.ENTITY_TYPE.containsId(id)) {
PresenceFootsteps.logger.warn("Locomotion registered for unknown entity type " + id);
}

values.put(id, Locomotion.byName(value.toUpperCase()));
values.put(id, Locomotion.byName(value.getAsString().toUpperCase()));
}

@Override
Expand Down
34 changes: 15 additions & 19 deletions src/main/java/eu/ha3/presencefootsteps/world/PFSolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public Association findAssociation(AssociationPool associations, LivingEntity pl

// we discard the normal block association, and mark the foliage as detected
if (foliage.isEmitter() && engine.getIsolator().blocks().getAssociation(above, Substrates.MESSY) == SoundsKey.MESSY_GROUND) {
return Association.of(above, pos, ply, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER, foliage);
return Association.of(above, pos, ply, false, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER, foliage);
}

return Association.NOT_EMITTER;
Expand Down Expand Up @@ -211,9 +211,9 @@ private Association findAssociation(AssociationPool associations, LivingEntity p

if (state.isLiquid()) {
if (state.getFluidState().isIn(FluidTags.LAVA)) {
return Association.of(state, pos.down(), player, SoundsKey.LAVAFINE, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
return Association.of(state, pos.down(), player, false, SoundsKey.LAVAFINE, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
}
return Association.of(state, pos.down(), player, SoundsKey.WATERFINE, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
return Association.of(state, pos.down(), player, false, SoundsKey.WATERFINE, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
}

return association;
Expand All @@ -237,30 +237,26 @@ private Association findAssociation(AssociationPool associations, LivingEntity e
target = carpet;
// reference frame moved up by 1
} else {
association = SoundsKey.UNASSIGNED;
pos.move(Direction.DOWN);
// This condition implies that if the carpet is NOT_EMITTER, solving will
// CONTINUE with the actual block surface the player is walking on
if (target.isAir()) {
pos.move(Direction.DOWN);
association = associations.get(pos, target, Substrates.DEFAULT);

// If the block surface we're on is not an emitter, check for fences below us
if (!association.isEmitter() || !association.isResult()) {
pos.move(Direction.DOWN);
BlockState fence = getBlockStateAt(entity, pos);

// Only check fences if we're actually touching them
if (checkCollision(entity.getWorld(), fence, pos, collider)) {
if ((association = associations.get(pos, fence, Substrates.FENCE)).isResult()) {
carpet = target;
target = fence;
// reference frame moved down by 1
} else {
pos.move(Direction.UP);
}
if (checkCollision(entity.getWorld(), fence, pos, collider) && (association = associations.get(pos, fence, Substrates.FENCE)).isResult()) {
carpet = target;
target = fence;
// reference frame moved down by 1
} else {
pos.move(Direction.UP);
}
}

if (!association.isResult()) {
association = associations.get(pos, target, Substrates.DEFAULT);
}

if (engine.getConfig().foliageSoundsVolume.get() > 0) {
if (entity.getEquippedStack(EquipmentSlot.FEET).isEmpty() || entity.isSprinting()) {
if (association.isEmitter() && carpet.getCollisionShape(entity.getWorld(), pos).isEmpty()) {
Expand Down Expand Up @@ -291,6 +287,6 @@ private Association findAssociation(AssociationPool associations, LivingEntity e
wetAssociation = associations.get(pos, target, Substrates.WET);
}

return Association.of(target, pos, entity, association, wetAssociation, foliage);
return Association.of(target, pos, entity, associations.wasLastMatchGolem() && entity.isOnGround(), association, wetAssociation, foliage);
}
}
Loading

0 comments on commit f3e93b0

Please sign in to comment.