2525import net .minecraft .world .World ;
2626import org .slf4j .Logger ;
2727
28+ import java .util .HashMap ;
29+ import java .util .Locale ;
30+ import java .util .Map ;
31+
2832public class SoundPlayerBlockEntity extends GlowcaseBlockEntity {
2933 private static final Logger LOGGER = LogUtils .getLogger ();
3034
@@ -37,6 +41,7 @@ public class SoundPlayerBlockEntity extends GlowcaseBlockEntity {
3741 public boolean relative = false ;
3842 public Vec3d offset = Vec3d .ZERO ;
3943 public boolean cancelOthers = false ;
44+ public PositionSampler volumeSampler = PositionSampler .CAMERA ;
4045
4146 public PositionedSoundLoop nowPlaying = null ;
4247
@@ -66,6 +71,7 @@ protected void writeNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryL
6671 Vec3d .CODEC .encodeStart (ops , this .offset )
6772 .resultOrPartial (LOGGER ::error )
6873 .ifPresent (result -> tag .put ("offset" , result ));
74+ tag .putString ("volumeSampler" , volumeSampler .name ());
6975 }
7076
7177 @ Override
@@ -88,6 +94,13 @@ protected void readNbt(NbtCompound tag, RegistryWrapper.WrapperLookup registryLo
8894 Vec3d .CODEC .parse (ops , tag .get ("offset" ))
8995 .resultOrPartial (LOGGER ::error )
9096 .ifPresent (result -> this .offset = result );
97+
98+ if (tag .contains ("volumeSampler" , NbtElement .STRING_TYPE )) {
99+ final PositionSampler sampler = PositionSampler .getByName (tag .getString ("volumeSampler" ));
100+ if (sampler != null ) {
101+ this .volumeSampler = sampler ;
102+ }
103+ }
91104 }
92105
93106 @ Environment (EnvType .CLIENT )
@@ -143,6 +156,45 @@ private float distanceSquared() {
143156 return this .distance * this .distance ;
144157 }
145158
159+
160+ public enum PositionSampler {
161+ CAMERA {
162+ @ Override
163+ public Vec3d getPosition (final MinecraftClient client ) {
164+ return client .gameRenderer .getCamera ().getPos ();
165+ }
166+ },
167+ PLAYER {
168+ @ Override
169+ public Vec3d getPosition (final MinecraftClient client ) {
170+ if (client .player == null ) {
171+ return Vec3d .ZERO ;
172+ }
173+ return client .player .getPos ();
174+ }
175+ },
176+ ;
177+
178+ private static final Map <String , PositionSampler > lookup ;
179+
180+ static {
181+ final Map <String , PositionSampler > samplers = new HashMap <>();
182+ for (final PositionSampler sampler : values ()) {
183+ samplers .put (sampler .name ().toLowerCase (Locale .ROOT ), sampler );
184+ }
185+ lookup = Map .copyOf (samplers );
186+ }
187+
188+ public static PositionSampler getByName (String value ) {
189+ if (value == null ) {
190+ return null ;
191+ }
192+ return lookup .get (value .toLowerCase (Locale .ROOT ));
193+ }
194+
195+ public abstract Vec3d getPosition (MinecraftClient client );
196+ }
197+
146198 // I don't think the repeat is necessary on this at this point
147199 public static class PositionedSoundLoop extends AbstractSoundInstance implements TickableSoundInstance {
148200 private final SoundPlayerBlockEntity soundBlock ;
@@ -213,8 +265,8 @@ public float getVolume() {
213265 }
214266
215267 private float linearFalloff () {
216- final Camera camera = MinecraftClient .getInstance (). gameRenderer . getCamera ( );
217- float distanceToCamera = (float ) this .soundBlock .getSourcePos ().distanceTo (camera . getPos () );
268+ final Vec3d position = this . soundBlock . volumeSampler . getPosition ( MinecraftClient .getInstance ());
269+ float distanceToCamera = (float ) this .soundBlock .getSourcePos ().distanceTo (position );
218270 return 1 - (distanceToCamera / this .soundBlock .distance );
219271 }
220272
0 commit comments