Skip to content

Commit f3e93b0

Browse files
committed
Merge branch '1.21' into 1.21.3
# Conflicts: # src/main/java/eu/ha3/presencefootsteps/sound/generator/TerrestrialStepSoundGenerator.java
2 parents ce4c732 + 0a8db26 commit f3e93b0

19 files changed

+555
-78
lines changed

src/main/java/eu/ha3/presencefootsteps/sound/Isolator.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import eu.ha3.presencefootsteps.util.JsonObjectWriter;
1414
import eu.ha3.presencefootsteps.util.ResourceUtils;
1515
import eu.ha3.presencefootsteps.util.BlockReport.Reportable;
16+
import eu.ha3.presencefootsteps.world.BiomeVarianceLookup;
1617
import eu.ha3.presencefootsteps.world.GolemLookup;
1718
import eu.ha3.presencefootsteps.world.HeuristicStateLookup;
1819
import eu.ha3.presencefootsteps.world.Index;
@@ -34,10 +35,12 @@ public record Isolator (
3435
HeuristicStateLookup heuristics,
3536
Lookup<EntityType<?>> golems,
3637
Lookup<BlockState> blocks,
38+
Index<Identifier, BiomeVarianceLookup.BiomeVariance> biomes,
3739
Lookup<SoundEvent> primitives,
3840
AcousticLibrary acoustics
3941
) implements Reportable {
4042
private static final Identifier BLOCK_MAP = PresenceFootsteps.id("config/blockmap.json");
43+
private static final Identifier BIOME_MAP = PresenceFootsteps.id("config/biomevariancemap.json");
4144
private static final Identifier GOLEM_MAP = PresenceFootsteps.id("config/golemmap.json");
4245
private static final Identifier LOCOMOTION_MAP = PresenceFootsteps.id("config/locomotionmap.json");
4346
private static final Identifier PRIMITIVE_MAP = PresenceFootsteps.id("config/primitivemap.json");
@@ -50,14 +53,16 @@ public Isolator(SoundEngine engine) {
5053
new HeuristicStateLookup(),
5154
new GolemLookup(),
5255
new StateLookup(),
56+
new BiomeVarianceLookup(),
5357
new PrimitiveLookup(),
5458
new AcousticsPlayer(new DelayedSoundPlayer(engine.soundPlayer))
5559
);
5660
}
5761

5862
public boolean load(ResourceManager manager) {
5963
boolean hasConfigurations = false;
60-
hasConfigurations |= ResourceUtils.forEachReverse(BLOCK_MAP, manager, blocks()::load);
64+
hasConfigurations |= ResourceUtils.forEach(BLOCK_MAP, manager, blocks()::load);
65+
hasConfigurations |= ResourceUtils.forEach(BIOME_MAP, manager, biomes()::load);
6166
hasConfigurations |= ResourceUtils.forEach(GOLEM_MAP, manager, golems()::load);
6267
hasConfigurations |= ResourceUtils.forEach(PRIMITIVE_MAP, manager, primitives()::load);
6368
hasConfigurations |= ResourceUtils.forEach(LOCOMOTION_MAP, manager, locomotions()::load);

src/main/java/eu/ha3/presencefootsteps/sound/generator/StepSoundGenerator.java

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
* @author Hurry
77
*/
88
public interface StepSoundGenerator {
9+
10+
float getLocalPitch(float tickDelta);
11+
12+
float getLocalVolume(float tickDelta);
13+
914
/**
1015
* Gets the motion tracker used to determine the direction and speed for an entity during simulation.
1116
*/

src/main/java/eu/ha3/presencefootsteps/sound/generator/TerrestrialStepSoundGenerator.java

+23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import net.minecraft.entity.LivingEntity;
88
import net.minecraft.entity.passive.AbstractHorseEntity;
99
import net.minecraft.entity.player.PlayerEntity;
10+
import net.minecraft.registry.RegistryKey;
1011
import net.minecraft.registry.tag.FluidTags;
1112
import net.minecraft.util.math.BlockPos;
1213
import org.jetbrains.annotations.Nullable;
@@ -15,11 +16,13 @@
1516
import eu.ha3.presencefootsteps.config.Variator;
1617
import eu.ha3.presencefootsteps.mixins.ILivingEntity;
1718
import eu.ha3.presencefootsteps.sound.State;
19+
import eu.ha3.presencefootsteps.util.Lerp;
1820
import eu.ha3.presencefootsteps.util.PlayerUtil;
1921
import eu.ha3.presencefootsteps.sound.Options;
2022
import eu.ha3.presencefootsteps.sound.SoundEngine;
2123
import eu.ha3.presencefootsteps.world.Association;
2224
import eu.ha3.presencefootsteps.world.AssociationPool;
25+
import eu.ha3.presencefootsteps.world.BiomeVarianceLookup;
2326
import eu.ha3.presencefootsteps.world.Solver;
2427
import eu.ha3.presencefootsteps.world.SoundsKey;
2528
import eu.ha3.presencefootsteps.world.Substrates;
@@ -58,20 +61,40 @@ class TerrestrialStepSoundGenerator implements StepSoundGenerator {
5861
protected final MotionTracker motionTracker = new MotionTracker(this);
5962
protected final AssociationPool associations;
6063

64+
private final Lerp biomePitch = new Lerp();
65+
private final Lerp biomeVolume = new Lerp();
66+
6167
public TerrestrialStepSoundGenerator(LivingEntity entity, SoundEngine engine, Modifier<TerrestrialStepSoundGenerator> modifier) {
6268
this.entity = entity;
6369
this.engine = engine;
6470
this.modifier = modifier;
6571
this.associations = new AssociationPool(entity, engine);
6672
}
6773

74+
@Override
75+
public float getLocalPitch(float tickDelta) {
76+
return biomePitch.get(tickDelta);
77+
}
78+
79+
@Override
80+
public float getLocalVolume(float tickDelta) {
81+
return biomeVolume.get(tickDelta);
82+
}
83+
6884
@Override
6985
public MotionTracker getMotionTracker() {
7086
return motionTracker;
7187
}
7288

7389
@Override
7490
public void generateFootsteps() {
91+
BiomeVarianceLookup.BiomeVariance variance = entity.getWorld().getBiome(entity.getBlockPos()).getKey().map(RegistryKey::getValue).map(key -> {
92+
return engine.getIsolator().biomes().lookup(key);
93+
}).orElse(BiomeVarianceLookup.BiomeVariance.DEFAULT);
94+
95+
biomePitch.update(variance.pitch(), 0.01F);
96+
biomeVolume.update(variance.volume(), 0.01F);
97+
7598
motionTracker.simulateMotionData(entity);
7699
simulateFootsteps();
77100
simulateAirborne();

src/main/java/eu/ha3/presencefootsteps/sound/player/ImmediateSoundPlayer.java

+9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import eu.ha3.presencefootsteps.util.PlayerUtil;
1212
import eu.ha3.presencefootsteps.sound.Options;
1313
import eu.ha3.presencefootsteps.sound.SoundEngine;
14+
import eu.ha3.presencefootsteps.sound.StepSoundSource;
15+
import eu.ha3.presencefootsteps.sound.generator.StepSoundGenerator;
1416

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

46+
StepSoundGenerator generator = ((StepSoundSource) location).getStepGenerator(engine).orElse(null);
47+
if (generator != null) {
48+
float tickDelta = mc.getRenderTickCounter().getTickDelta(false);
49+
volume *= generator.getLocalVolume(tickDelta);
50+
pitch *= generator.getLocalPitch(tickDelta);
51+
}
52+
4453
PositionedSoundInstance sound = new UncappedSoundInstance(soundName, volume, pitch, location);
4554

4655
if (distance > 100) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package eu.ha3.presencefootsteps.util;
2+
3+
import net.minecraft.util.math.MathHelper;
4+
5+
public class Lerp {
6+
public float previous;
7+
public float current;
8+
9+
public void update(float newTarget, float rate) {
10+
previous = current;
11+
if (current < newTarget) {
12+
current = Math.min(current + rate, newTarget);
13+
}
14+
if (current > newTarget) {
15+
current = Math.max(current - rate, newTarget);
16+
}
17+
}
18+
19+
public float get(float tickDelta) {
20+
return MathHelper.lerp(tickDelta, previous, current);
21+
}
22+
}

src/main/java/eu/ha3/presencefootsteps/world/AbstractSubstrateLookup.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import org.jetbrains.annotations.Nullable;
77

8+
import com.google.gson.JsonElement;
9+
810
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
911
import net.minecraft.util.Identifier;
1012

@@ -46,14 +48,14 @@ public Set<String> getSubstrates() {
4648
}
4749

4850
@Override
49-
public void add(String key, String value) {
51+
public void add(String key, JsonElement value) {
5052
final String[] split = key.trim().split("@");
5153
final String primitive = split[0];
5254
final String substrate = split.length > 1 ? split[1] : Substrates.DEFAULT;
5355

5456
substrates
5557
.computeIfAbsent(substrate, s -> new Object2ObjectLinkedOpenHashMap<>())
56-
.put(Identifier.of(primitive), SoundsKey.of(value));
58+
.put(Identifier.of(primitive), SoundsKey.of(value.getAsString()));
5759
}
5860

5961
@Override

src/main/java/eu/ha3/presencefootsteps/world/Association.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,27 @@ public record Association (
1313
BlockState state,
1414
BlockPos pos,
1515
@Nullable LivingEntity source,
16+
boolean forcePlay,
1617

1718
SoundsKey dry,
1819
SoundsKey wet,
1920
SoundsKey foliage
2021
) {
21-
public static final Association NOT_EMITTER = new Association(Blocks.AIR.getDefaultState(), BlockPos.ORIGIN, null, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
22+
public static final Association NOT_EMITTER = new Association(Blocks.AIR.getDefaultState(), BlockPos.ORIGIN, null, false, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
2223

23-
public static Association of(BlockState state, BlockPos pos, LivingEntity source, SoundsKey dry, SoundsKey wet, SoundsKey foliage) {
24+
public static Association of(BlockState state, BlockPos pos, LivingEntity source, boolean forcePlay, SoundsKey dry, SoundsKey wet, SoundsKey foliage) {
2425
if (dry.isSilent() && wet.isSilent() && foliage.isSilent()) {
2526
return NOT_EMITTER;
2627
}
27-
return new Association(state, pos.toImmutable(), source, dry, wet, foliage);
28+
return new Association(state, pos.toImmutable(), source, forcePlay, dry, wet, foliage);
2829
}
2930

3031
public boolean isResult() {
3132
return dry.isResult() || wet.isResult() || foliage.isResult();
3233
}
3334

3435
public boolean isSilent() {
35-
return this == NOT_EMITTER || state.isAir();
36+
return this == NOT_EMITTER || (state.isAir() && !forcePlay);
3637
}
3738

3839
public boolean dataEquals(Association other) {

src/main/java/eu/ha3/presencefootsteps/world/AssociationPool.java

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public SoundsKey get(BlockPos pos, BlockState state, String substrate) {
6969
return !e.isCollidable() || e.getBoundingBox().maxY < entity.getY() + 0.2F;
7070
})) {
7171
if ((association = engine.getIsolator().golems().getAssociation(golem.getType(), substrate)).isEmitter()) {
72+
wasGolem = true;
7273
return association;
7374
}
7475
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package eu.ha3.presencefootsteps.world;
2+
3+
import java.io.IOException;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
import com.google.gson.JsonElement;
8+
import com.mojang.datafixers.util.Pair;
9+
import com.mojang.serialization.Codec;
10+
import com.mojang.serialization.JsonOps;
11+
import com.mojang.serialization.codecs.RecordCodecBuilder;
12+
13+
import eu.ha3.presencefootsteps.util.JsonObjectWriter;
14+
import net.minecraft.sound.BlockSoundGroup;
15+
import net.minecraft.util.Identifier;
16+
17+
public class BiomeVarianceLookup implements Index<Identifier, BiomeVarianceLookup.BiomeVariance> {
18+
private final Map<Identifier, BiomeVariance> entries = new HashMap<>();
19+
20+
@Override
21+
public BiomeVariance lookup(Identifier key) {
22+
return entries.getOrDefault(key, BiomeVariance.DEFAULT);
23+
}
24+
25+
@Override
26+
public boolean contains(Identifier key) {
27+
return entries.containsKey(key);
28+
}
29+
30+
@Override
31+
public void add(String key, JsonElement value) {
32+
BiomeVariance.CODEC.decode(JsonOps.INSTANCE, value).result().map(Pair::getFirst).ifPresent(i -> {
33+
entries.put(Identifier.of(key), i);
34+
});
35+
}
36+
37+
@Override
38+
public void writeToReport(boolean full, JsonObjectWriter writer, Map<String, BlockSoundGroup> groups) throws IOException {
39+
}
40+
41+
public record BiomeVariance(float volume, float pitch) {
42+
public static final BiomeVariance DEFAULT = new BiomeVariance(1, 1);
43+
static final Codec<BiomeVariance> CODEC = RecordCodecBuilder.create(i -> i.group(
44+
Codec.FLOAT.fieldOf("volume").forGetter(BiomeVariance::volume),
45+
Codec.FLOAT.fieldOf("pitch").forGetter(BiomeVariance::pitch)
46+
).apply(i, BiomeVariance::new));
47+
}
48+
}

src/main/java/eu/ha3/presencefootsteps/world/Loadable.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.Reader;
44

55
import com.google.gson.Gson;
6+
import com.google.gson.JsonElement;
67
import com.google.gson.JsonObject;
78

89
public interface Loadable {
@@ -11,7 +12,7 @@ public interface Loadable {
1112
/**
1213
* Register a blockmap entry.
1314
*/
14-
void add(String key, String value);
15+
void add(String key, JsonElement json);
1516

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

2324
json.entrySet().forEach(entry -> {
24-
add(entry.getKey(), entry.getValue().getAsString());
25+
add(entry.getKey(), entry.getValue());
2526
});
2627
}
2728
}

src/main/java/eu/ha3/presencefootsteps/world/LocomotionLookup.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import java.io.IOException;
1919
import java.util.Map;
2020

21+
import com.google.gson.JsonElement;
22+
2123
public class LocomotionLookup implements Index<Entity, Locomotion> {
2224
private final Map<Identifier, Locomotion> values = new Object2ObjectLinkedOpenHashMap<>();
2325

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

3840
@Override
39-
public void add(String key, String value) {
41+
public void add(String key, JsonElement value) {
4042
Identifier id = Identifier.of(key);
4143

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

46-
values.put(id, Locomotion.byName(value.toUpperCase()));
48+
values.put(id, Locomotion.byName(value.getAsString().toUpperCase()));
4749
}
4850

4951
@Override

src/main/java/eu/ha3/presencefootsteps/world/PFSolver.java

+15-19
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public Association findAssociation(AssociationPool associations, LivingEntity pl
8080

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

8686
return Association.NOT_EMITTER;
@@ -211,9 +211,9 @@ private Association findAssociation(AssociationPool associations, LivingEntity p
211211

212212
if (state.isLiquid()) {
213213
if (state.getFluidState().isIn(FluidTags.LAVA)) {
214-
return Association.of(state, pos.down(), player, SoundsKey.LAVAFINE, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
214+
return Association.of(state, pos.down(), player, false, SoundsKey.LAVAFINE, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
215215
}
216-
return Association.of(state, pos.down(), player, SoundsKey.WATERFINE, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
216+
return Association.of(state, pos.down(), player, false, SoundsKey.WATERFINE, SoundsKey.NON_EMITTER, SoundsKey.NON_EMITTER);
217217
}
218218

219219
return association;
@@ -237,30 +237,26 @@ private Association findAssociation(AssociationPool associations, LivingEntity e
237237
target = carpet;
238238
// reference frame moved up by 1
239239
} else {
240-
association = SoundsKey.UNASSIGNED;
241-
pos.move(Direction.DOWN);
242240
// This condition implies that if the carpet is NOT_EMITTER, solving will
243241
// CONTINUE with the actual block surface the player is walking on
244-
if (target.isAir()) {
242+
pos.move(Direction.DOWN);
243+
association = associations.get(pos, target, Substrates.DEFAULT);
244+
245+
// If the block surface we're on is not an emitter, check for fences below us
246+
if (!association.isEmitter() || !association.isResult()) {
245247
pos.move(Direction.DOWN);
246248
BlockState fence = getBlockStateAt(entity, pos);
247249

248250
// Only check fences if we're actually touching them
249-
if (checkCollision(entity.getWorld(), fence, pos, collider)) {
250-
if ((association = associations.get(pos, fence, Substrates.FENCE)).isResult()) {
251-
carpet = target;
252-
target = fence;
253-
// reference frame moved down by 1
254-
} else {
255-
pos.move(Direction.UP);
256-
}
251+
if (checkCollision(entity.getWorld(), fence, pos, collider) && (association = associations.get(pos, fence, Substrates.FENCE)).isResult()) {
252+
carpet = target;
253+
target = fence;
254+
// reference frame moved down by 1
255+
} else {
256+
pos.move(Direction.UP);
257257
}
258258
}
259259

260-
if (!association.isResult()) {
261-
association = associations.get(pos, target, Substrates.DEFAULT);
262-
}
263-
264260
if (engine.getConfig().foliageSoundsVolume.get() > 0) {
265261
if (entity.getEquippedStack(EquipmentSlot.FEET).isEmpty() || entity.isSprinting()) {
266262
if (association.isEmitter() && carpet.getCollisionShape(entity.getWorld(), pos).isEmpty()) {
@@ -291,6 +287,6 @@ private Association findAssociation(AssociationPool associations, LivingEntity e
291287
wetAssociation = associations.get(pos, target, Substrates.WET);
292288
}
293289

294-
return Association.of(target, pos, entity, association, wetAssociation, foliage);
290+
return Association.of(target, pos, entity, associations.wasLastMatchGolem() && entity.isOnGround(), association, wetAssociation, foliage);
295291
}
296292
}

0 commit comments

Comments
 (0)