mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-15 11:45:42 +00:00
Track owning entity when sending sounds
This allows us to sync the position to the entity immediately, rather than the sound jumping about. Someone has set up rick-rolling pocket computers (<3 to whoever did this), and the lag on them irritates me enough to fix this. Fixes #1074
This commit is contained in:
parent
118b89ea41
commit
9cb7a5bec7
@ -6,11 +6,11 @@
|
|||||||
package dan200.computercraft.client.sound;
|
package dan200.computercraft.client.sound;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.audio.SoundHandler;
|
import net.minecraft.client.audio.SoundHandler;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance of a speaker, which is either playing a {@link DfpwmStream} stream or a normal sound.
|
* An instance of a speaker, which is either playing a {@link DfpwmStream} stream or a normal sound.
|
||||||
@ -44,7 +44,7 @@ public class SpeakerInstance
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playAudio( Vector3d position, float volume )
|
public void playAudio( SpeakerPosition position, float volume )
|
||||||
{
|
{
|
||||||
SoundHandler soundManager = Minecraft.getInstance().getSoundManager();
|
SoundHandler soundManager = Minecraft.getInstance().getSoundManager();
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ public class SpeakerInstance
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playSound( Vector3d position, ResourceLocation location, float volume, float pitch )
|
public void playSound( SpeakerPosition position, ResourceLocation location, float volume, float pitch )
|
||||||
{
|
{
|
||||||
SoundHandler soundManager = Minecraft.getInstance().getSoundManager();
|
SoundHandler soundManager = Minecraft.getInstance().getSoundManager();
|
||||||
currentStream = null;
|
currentStream = null;
|
||||||
@ -78,7 +78,7 @@ public class SpeakerInstance
|
|||||||
soundManager.play( sound );
|
soundManager.play( sound );
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPosition( Vector3d position )
|
void setPosition( SpeakerPosition position )
|
||||||
{
|
{
|
||||||
if( sound != null ) sound.setPosition( position );
|
if( sound != null ) sound.setPosition( position );
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.client.sound;
|
package dan200.computercraft.client.sound;
|
||||||
|
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.client.event.sound.PlayStreamingSourceEvent;
|
import net.minecraftforge.client.event.sound.PlayStreamingSourceEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
@ -48,7 +48,7 @@ public class SpeakerManager
|
|||||||
if( sound != null ) sound.stop();
|
if( sound != null ) sound.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void moveSound( UUID source, Vector3d position )
|
public static void moveSound( UUID source, SpeakerPosition position )
|
||||||
{
|
{
|
||||||
SpeakerInstance sound = sounds.get( source );
|
SpeakerInstance sound = sounds.get( source );
|
||||||
if( sound != null ) sound.setPosition( position );
|
if( sound != null ) sound.setPosition( position );
|
||||||
|
@ -5,13 +5,14 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.client.sound;
|
package dan200.computercraft.client.sound;
|
||||||
|
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||||
import net.minecraft.client.audio.IAudioStream;
|
import net.minecraft.client.audio.IAudioStream;
|
||||||
import net.minecraft.client.audio.ITickableSound;
|
import net.minecraft.client.audio.ITickableSound;
|
||||||
import net.minecraft.client.audio.LocatableSound;
|
import net.minecraft.client.audio.LocatableSound;
|
||||||
import net.minecraft.client.audio.SoundSource;
|
import net.minecraft.client.audio.SoundSource;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.SoundCategory;
|
import net.minecraft.util.SoundCategory;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@ -22,7 +23,11 @@ public class SpeakerSound extends LocatableSound implements ITickableSound
|
|||||||
Executor executor;
|
Executor executor;
|
||||||
DfpwmStream stream;
|
DfpwmStream stream;
|
||||||
|
|
||||||
SpeakerSound( ResourceLocation sound, DfpwmStream stream, Vector3d position, float volume, float pitch )
|
private Entity entity;
|
||||||
|
|
||||||
|
private boolean stopped = false;
|
||||||
|
|
||||||
|
SpeakerSound( ResourceLocation sound, DfpwmStream stream, SpeakerPosition position, float volume, float pitch )
|
||||||
{
|
{
|
||||||
super( sound, SoundCategory.RECORDS );
|
super( sound, SoundCategory.RECORDS );
|
||||||
setPosition( position );
|
setPosition( position );
|
||||||
@ -32,22 +37,35 @@ public class SpeakerSound extends LocatableSound implements ITickableSound
|
|||||||
attenuation = AttenuationType.LINEAR;
|
attenuation = AttenuationType.LINEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPosition( Vector3d position )
|
void setPosition( SpeakerPosition position )
|
||||||
{
|
{
|
||||||
x = (float) position.x();
|
x = position.position().x;
|
||||||
y = (float) position.y();
|
y = position.position().y;
|
||||||
z = (float) position.z();
|
z = position.position().z;
|
||||||
|
entity = position.entity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isStopped()
|
public boolean isStopped()
|
||||||
{
|
{
|
||||||
return false;
|
return stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick()
|
public void tick()
|
||||||
{
|
{
|
||||||
|
if( entity == null ) return;
|
||||||
|
if( !entity.isAlive() )
|
||||||
|
{
|
||||||
|
stopped = true;
|
||||||
|
looping = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = entity.getX();
|
||||||
|
y = entity.getY();
|
||||||
|
z = entity.getZ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -7,8 +7,8 @@ package dan200.computercraft.shared.network.client;
|
|||||||
|
|
||||||
import dan200.computercraft.client.sound.SpeakerManager;
|
import dan200.computercraft.client.sound.SpeakerManager;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
@ -27,14 +27,14 @@ import java.util.UUID;
|
|||||||
public class SpeakerAudioClientMessage implements NetworkMessage
|
public class SpeakerAudioClientMessage implements NetworkMessage
|
||||||
{
|
{
|
||||||
private final UUID source;
|
private final UUID source;
|
||||||
private final Vector3d pos;
|
private final SpeakerPosition.Message pos;
|
||||||
private final ByteBuffer content;
|
private final ByteBuffer content;
|
||||||
private final float volume;
|
private final float volume;
|
||||||
|
|
||||||
public SpeakerAudioClientMessage( UUID source, Vector3d pos, float volume, ByteBuffer content )
|
public SpeakerAudioClientMessage( UUID source, SpeakerPosition pos, float volume, ByteBuffer content )
|
||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.pos = pos;
|
this.pos = pos.asMessage();
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.volume = volume;
|
this.volume = volume;
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ public class SpeakerAudioClientMessage implements NetworkMessage
|
|||||||
public SpeakerAudioClientMessage( PacketBuffer buf )
|
public SpeakerAudioClientMessage( PacketBuffer buf )
|
||||||
{
|
{
|
||||||
source = buf.readUUID();
|
source = buf.readUUID();
|
||||||
pos = new Vector3d( buf.readDouble(), buf.readDouble(), buf.readDouble() );
|
pos = SpeakerPosition.Message.read( buf );
|
||||||
volume = buf.readFloat();
|
volume = buf.readFloat();
|
||||||
|
|
||||||
SpeakerManager.getSound( source ).pushAudio( buf );
|
SpeakerManager.getSound( source ).pushAudio( buf );
|
||||||
@ -53,9 +53,7 @@ public class SpeakerAudioClientMessage implements NetworkMessage
|
|||||||
public void toBytes( @Nonnull PacketBuffer buf )
|
public void toBytes( @Nonnull PacketBuffer buf )
|
||||||
{
|
{
|
||||||
buf.writeUUID( source );
|
buf.writeUUID( source );
|
||||||
buf.writeDouble( pos.x() );
|
pos.write( buf );
|
||||||
buf.writeDouble( pos.y() );
|
|
||||||
buf.writeDouble( pos.z() );
|
|
||||||
buf.writeFloat( volume );
|
buf.writeFloat( volume );
|
||||||
buf.writeBytes( content.duplicate() );
|
buf.writeBytes( content.duplicate() );
|
||||||
}
|
}
|
||||||
@ -64,6 +62,6 @@ public class SpeakerAudioClientMessage implements NetworkMessage
|
|||||||
@OnlyIn( Dist.CLIENT )
|
@OnlyIn( Dist.CLIENT )
|
||||||
public void handle( NetworkEvent.Context context )
|
public void handle( NetworkEvent.Context context )
|
||||||
{
|
{
|
||||||
SpeakerManager.getSound( source ).playAudio( pos, volume );
|
SpeakerManager.getSound( source ).playAudio( pos.reify(), volume );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ package dan200.computercraft.shared.network.client;
|
|||||||
|
|
||||||
import dan200.computercraft.client.sound.SpeakerManager;
|
import dan200.computercraft.client.sound.SpeakerManager;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
@ -26,33 +26,31 @@ import java.util.UUID;
|
|||||||
public class SpeakerMoveClientMessage implements NetworkMessage
|
public class SpeakerMoveClientMessage implements NetworkMessage
|
||||||
{
|
{
|
||||||
private final UUID source;
|
private final UUID source;
|
||||||
private final Vector3d pos;
|
private final SpeakerPosition.Message pos;
|
||||||
|
|
||||||
public SpeakerMoveClientMessage( UUID source, Vector3d pos )
|
public SpeakerMoveClientMessage( UUID source, SpeakerPosition pos )
|
||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.pos = pos;
|
this.pos = pos.asMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpeakerMoveClientMessage( PacketBuffer buf )
|
public SpeakerMoveClientMessage( PacketBuffer buf )
|
||||||
{
|
{
|
||||||
source = buf.readUUID();
|
source = buf.readUUID();
|
||||||
pos = new Vector3d( buf.readDouble(), buf.readDouble(), buf.readDouble() );
|
pos = SpeakerPosition.Message.read( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toBytes( @Nonnull PacketBuffer buf )
|
public void toBytes( @Nonnull PacketBuffer buf )
|
||||||
{
|
{
|
||||||
buf.writeUUID( source );
|
buf.writeUUID( source );
|
||||||
buf.writeDouble( pos.x() );
|
pos.write( buf );
|
||||||
buf.writeDouble( pos.y() );
|
|
||||||
buf.writeDouble( pos.z() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@OnlyIn( Dist.CLIENT )
|
@OnlyIn( Dist.CLIENT )
|
||||||
public void handle( NetworkEvent.Context context )
|
public void handle( NetworkEvent.Context context )
|
||||||
{
|
{
|
||||||
SpeakerManager.moveSound( source, pos );
|
SpeakerManager.moveSound( source, pos.reify() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@ package dan200.computercraft.shared.network.client;
|
|||||||
|
|
||||||
import dan200.computercraft.client.sound.SpeakerManager;
|
import dan200.computercraft.client.sound.SpeakerManager;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||||
import net.minecraft.network.PacketBuffer;
|
import net.minecraft.network.PacketBuffer;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
@ -27,15 +27,15 @@ import java.util.UUID;
|
|||||||
public class SpeakerPlayClientMessage implements NetworkMessage
|
public class SpeakerPlayClientMessage implements NetworkMessage
|
||||||
{
|
{
|
||||||
private final UUID source;
|
private final UUID source;
|
||||||
private final Vector3d pos;
|
private final SpeakerPosition.Message pos;
|
||||||
private final ResourceLocation sound;
|
private final ResourceLocation sound;
|
||||||
private final float volume;
|
private final float volume;
|
||||||
private final float pitch;
|
private final float pitch;
|
||||||
|
|
||||||
public SpeakerPlayClientMessage( UUID source, Vector3d pos, ResourceLocation event, float volume, float pitch )
|
public SpeakerPlayClientMessage( UUID source, SpeakerPosition pos, ResourceLocation event, float volume, float pitch )
|
||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.pos = pos;
|
this.pos = pos.asMessage();
|
||||||
sound = event;
|
sound = event;
|
||||||
this.volume = volume;
|
this.volume = volume;
|
||||||
this.pitch = pitch;
|
this.pitch = pitch;
|
||||||
@ -44,7 +44,7 @@ public class SpeakerPlayClientMessage implements NetworkMessage
|
|||||||
public SpeakerPlayClientMessage( PacketBuffer buf )
|
public SpeakerPlayClientMessage( PacketBuffer buf )
|
||||||
{
|
{
|
||||||
source = buf.readUUID();
|
source = buf.readUUID();
|
||||||
pos = new Vector3d( buf.readDouble(), buf.readDouble(), buf.readDouble() );
|
pos = SpeakerPosition.Message.read( buf );
|
||||||
sound = buf.readResourceLocation();
|
sound = buf.readResourceLocation();
|
||||||
volume = buf.readFloat();
|
volume = buf.readFloat();
|
||||||
pitch = buf.readFloat();
|
pitch = buf.readFloat();
|
||||||
@ -54,9 +54,7 @@ public class SpeakerPlayClientMessage implements NetworkMessage
|
|||||||
public void toBytes( @Nonnull PacketBuffer buf )
|
public void toBytes( @Nonnull PacketBuffer buf )
|
||||||
{
|
{
|
||||||
buf.writeUUID( source );
|
buf.writeUUID( source );
|
||||||
buf.writeDouble( pos.x() );
|
pos.write( buf );
|
||||||
buf.writeDouble( pos.y() );
|
|
||||||
buf.writeDouble( pos.z() );
|
|
||||||
buf.writeResourceLocation( sound );
|
buf.writeResourceLocation( sound );
|
||||||
buf.writeFloat( volume );
|
buf.writeFloat( volume );
|
||||||
buf.writeFloat( pitch );
|
buf.writeFloat( pitch );
|
||||||
@ -66,6 +64,6 @@ public class SpeakerPlayClientMessage implements NetworkMessage
|
|||||||
@OnlyIn( Dist.CLIENT )
|
@OnlyIn( Dist.CLIENT )
|
||||||
public void handle( NetworkEvent.Context context )
|
public void handle( NetworkEvent.Context context )
|
||||||
{
|
{
|
||||||
SpeakerManager.getSound( source ).playSound( pos, sound, volume, pitch );
|
SpeakerManager.getSound( source ).playSound( pos.reify(), sound, volume, pitch );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ import net.minecraft.util.math.vector.Vector3d;
|
|||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static dan200.computercraft.api.lua.LuaValues.checkFinite;
|
import static dan200.computercraft.api.lua.LuaValues.checkFinite;
|
||||||
@ -57,7 +56,7 @@ public abstract class SpeakerPeripheral implements IPeripheral
|
|||||||
|
|
||||||
private long clock = 0;
|
private long clock = 0;
|
||||||
private long lastPositionTime;
|
private long lastPositionTime;
|
||||||
private Vector3d lastPosition;
|
private SpeakerPosition lastPosition;
|
||||||
|
|
||||||
private long lastPlayTime;
|
private long lastPlayTime;
|
||||||
|
|
||||||
@ -72,10 +71,11 @@ public abstract class SpeakerPeripheral implements IPeripheral
|
|||||||
{
|
{
|
||||||
clock++;
|
clock++;
|
||||||
|
|
||||||
Vector3d pos = getPosition();
|
SpeakerPosition position = getPosition();
|
||||||
World world = getWorld();
|
World level = position.level();
|
||||||
if( world == null ) return;
|
Vector3d pos = position.position();
|
||||||
MinecraftServer server = world.getServer();
|
if( level == null ) return;
|
||||||
|
MinecraftServer server = level.getServer();
|
||||||
|
|
||||||
synchronized( pendingNotes )
|
synchronized( pendingNotes )
|
||||||
{
|
{
|
||||||
@ -83,7 +83,7 @@ public abstract class SpeakerPeripheral implements IPeripheral
|
|||||||
{
|
{
|
||||||
lastPlayTime = clock;
|
lastPlayTime = clock;
|
||||||
server.getPlayerList().broadcast(
|
server.getPlayerList().broadcast(
|
||||||
null, pos.x, pos.y, pos.z, sound.volume * 16, world.dimension(),
|
null, pos.x, pos.y, pos.z, sound.volume * 16, level.dimension(),
|
||||||
new SPlaySoundPacket( sound.location, SoundCategory.RECORDS, pos, sound.volume, sound.pitch )
|
new SPlaySoundPacket( sound.location, SoundCategory.RECORDS, pos, sound.volume, sound.pitch )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -125,20 +125,20 @@ public abstract class SpeakerPeripheral implements IPeripheral
|
|||||||
{
|
{
|
||||||
lastPlayTime = clock;
|
lastPlayTime = clock;
|
||||||
NetworkHandler.sendToAllAround(
|
NetworkHandler.sendToAllAround(
|
||||||
new SpeakerPlayClientMessage( getSource(), pos, sound.location, sound.volume, sound.pitch ),
|
new SpeakerPlayClientMessage( getSource(), position, sound.location, sound.volume, sound.pitch ),
|
||||||
world, pos, sound.volume * 16
|
level, pos, sound.volume * 16
|
||||||
);
|
);
|
||||||
syncedPosition( pos );
|
syncedPosition( position );
|
||||||
}
|
}
|
||||||
else if( dfpwmState != null && dfpwmState.shouldSendPending( now ) )
|
else if( dfpwmState != null && dfpwmState.shouldSendPending( now ) )
|
||||||
{
|
{
|
||||||
// If clients need to receive another batch of audio, send it and then notify computers our internal buffer is
|
// If clients need to receive another batch of audio, send it and then notify computers our internal buffer is
|
||||||
// free again.
|
// free again.
|
||||||
NetworkHandler.sendToAllTracking(
|
NetworkHandler.sendToAllTracking(
|
||||||
new SpeakerAudioClientMessage( getSource(), pos, dfpwmState.getVolume(), dfpwmState.pullPending( now ) ),
|
new SpeakerAudioClientMessage( getSource(), position, dfpwmState.getVolume(), dfpwmState.pullPending( now ) ),
|
||||||
getWorld().getChunkAt( new BlockPos( pos ) )
|
level.getChunkAt( new BlockPos( pos ) )
|
||||||
);
|
);
|
||||||
syncedPosition( pos );
|
syncedPosition( position );
|
||||||
|
|
||||||
// And notify computers that we have space for more audio.
|
// And notify computers that we have space for more audio.
|
||||||
synchronized( computers )
|
synchronized( computers )
|
||||||
@ -153,25 +153,19 @@ public abstract class SpeakerPeripheral implements IPeripheral
|
|||||||
// Push position updates to any speakers which have ever played a note,
|
// Push position updates to any speakers which have ever played a note,
|
||||||
// have moved by a non-trivial amount and haven't had a position update
|
// have moved by a non-trivial amount and haven't had a position update
|
||||||
// in the last second.
|
// in the last second.
|
||||||
if( lastPosition != null && (clock - lastPositionTime) >= 20 )
|
if( lastPosition != null && (clock - lastPositionTime) >= 20 && !lastPosition.withinDistance( position, 0.1 ) )
|
||||||
{
|
|
||||||
Vector3d position = getPosition();
|
|
||||||
if( lastPosition.distanceToSqr( position ) >= 0.1 )
|
|
||||||
{
|
{
|
||||||
|
// TODO: What to do when entities move away? How do we notify people left behind that they're gone.
|
||||||
NetworkHandler.sendToAllTracking(
|
NetworkHandler.sendToAllTracking(
|
||||||
new SpeakerMoveClientMessage( getSource(), position ),
|
new SpeakerMoveClientMessage( getSource(), position ),
|
||||||
getWorld().getChunkAt( new BlockPos( position ) )
|
level.getChunkAt( new BlockPos( pos ) )
|
||||||
);
|
);
|
||||||
syncedPosition( position );
|
syncedPosition( position );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public abstract World getWorld();
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public abstract Vector3d getPosition();
|
public abstract SpeakerPosition getPosition();
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public UUID getSource()
|
public UUID getSource()
|
||||||
@ -373,7 +367,7 @@ public abstract class SpeakerPeripheral implements IPeripheral
|
|||||||
shouldStop = true;
|
shouldStop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncedPosition( Vector3d position )
|
private void syncedPosition( SpeakerPosition position )
|
||||||
{
|
{
|
||||||
lastPosition = position;
|
lastPosition = position;
|
||||||
lastPositionTime = clock;
|
lastPositionTime = clock;
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.shared.peripheral.speaker;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.network.PacketBuffer;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
public final class SpeakerPosition
|
||||||
|
{
|
||||||
|
private final World level;
|
||||||
|
private final Vector3d position;
|
||||||
|
private final Entity entity;
|
||||||
|
|
||||||
|
private SpeakerPosition( @Nullable World level, @Nonnull Vector3d position, @Nullable Entity entity )
|
||||||
|
{
|
||||||
|
this.level = level;
|
||||||
|
this.position = position;
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpeakerPosition of( @Nullable World level, @Nonnull Vector3d position )
|
||||||
|
{
|
||||||
|
return new SpeakerPosition( level, position, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpeakerPosition of( @Nonnull Entity entity )
|
||||||
|
{
|
||||||
|
return new SpeakerPosition( entity.level, entity.getEyePosition( 1 ), entity );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public World level()
|
||||||
|
{
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public Vector3d position()
|
||||||
|
{
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Entity entity()
|
||||||
|
{
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean withinDistance( SpeakerPosition other, double distanceSq )
|
||||||
|
{
|
||||||
|
return level == other.level && entity == other.entity && position.distanceToSqr( other.position ) <= distanceSq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message asMessage()
|
||||||
|
{
|
||||||
|
if( level == null ) throw new NullPointerException( "Cannot send a position without a level" );
|
||||||
|
return new Message( level.dimension().getRegistryName(), position, entity == null ? OptionalInt.empty() : OptionalInt.of( entity.getId() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Message
|
||||||
|
{
|
||||||
|
private final ResourceLocation level;
|
||||||
|
private final Vector3d position;
|
||||||
|
private final OptionalInt entity;
|
||||||
|
|
||||||
|
private Message( ResourceLocation level, Vector3d position, OptionalInt entity )
|
||||||
|
{
|
||||||
|
this.level = level;
|
||||||
|
this.position = position;
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message read( @Nonnull PacketBuffer buffer )
|
||||||
|
{
|
||||||
|
ResourceLocation level = buffer.readResourceLocation();
|
||||||
|
Vector3d position = new Vector3d( buffer.readDouble(), buffer.readDouble(), buffer.readDouble() );
|
||||||
|
OptionalInt entity = buffer.readBoolean() ? OptionalInt.of( buffer.readInt() ) : OptionalInt.empty();
|
||||||
|
return new Message( level, position, entity );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write( @Nonnull PacketBuffer buffer )
|
||||||
|
{
|
||||||
|
buffer.writeResourceLocation( level );
|
||||||
|
|
||||||
|
buffer.writeDouble( position.x );
|
||||||
|
buffer.writeDouble( position.y );
|
||||||
|
buffer.writeDouble( position.z );
|
||||||
|
|
||||||
|
buffer.writeBoolean( entity.isPresent() );
|
||||||
|
if( entity.isPresent() ) buffer.writeInt( entity.getAsInt() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public SpeakerPosition reify()
|
||||||
|
{
|
||||||
|
Minecraft minecraft = Minecraft.getInstance();
|
||||||
|
World level = minecraft.level;
|
||||||
|
if( level != null && !level.dimension().getRegistryName().equals( this.level ) ) level = null;
|
||||||
|
|
||||||
|
return new SpeakerPosition(
|
||||||
|
level, position,
|
||||||
|
level != null && entity.isPresent() ? level.getEntity( entity.getAsInt() ) : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,6 @@ import net.minecraft.tileentity.ITickableTileEntity;
|
|||||||
import net.minecraft.tileentity.TileEntityType;
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
import net.minecraft.world.World;
|
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
@ -79,17 +78,11 @@ public class TileSpeaker extends TileGeneric implements ITickableTileEntity
|
|||||||
this.speaker = speaker;
|
this.speaker = speaker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public World getWorld()
|
|
||||||
{
|
|
||||||
return speaker.getLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Vector3d getPosition()
|
public SpeakerPosition getPosition()
|
||||||
{
|
{
|
||||||
return Vector3d.atCenterOf( speaker.getBlockPos() );
|
return SpeakerPosition.of( speaker.getLevel(), Vector3d.atCenterOf( speaker.getBlockPos() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,6 +17,7 @@ import dan200.computercraft.shared.network.NetworkHandler;
|
|||||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
@ -61,6 +62,11 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
|
|||||||
LivingEntity living = (LivingEntity) entity;
|
LivingEntity living = (LivingEntity) entity;
|
||||||
return living.getMainHandItem() == stack || living.getOffhandItem() == stack ? entity : null;
|
return living.getMainHandItem() == stack || living.getOffhandItem() == stack ? entity : null;
|
||||||
}
|
}
|
||||||
|
else if( entity instanceof ItemEntity )
|
||||||
|
{
|
||||||
|
ItemEntity itemEntity = (ItemEntity) entity;
|
||||||
|
return itemEntity.getItem() == stack ? entity : null;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
@ -9,7 +9,6 @@ import dan200.computercraft.api.peripheral.IPeripheral;
|
|||||||
import dan200.computercraft.api.pocket.AbstractPocketUpgrade;
|
import dan200.computercraft.api.pocket.AbstractPocketUpgrade;
|
||||||
import dan200.computercraft.api.pocket.IPocketAccess;
|
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||||
import dan200.computercraft.shared.Registry;
|
import dan200.computercraft.shared.Registry;
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -26,23 +25,13 @@ public class PocketSpeaker extends AbstractPocketUpgrade
|
|||||||
@Override
|
@Override
|
||||||
public IPeripheral createPeripheral( @Nonnull IPocketAccess access )
|
public IPeripheral createPeripheral( @Nonnull IPocketAccess access )
|
||||||
{
|
{
|
||||||
return new PocketSpeakerPeripheral();
|
return new PocketSpeakerPeripheral( access );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )
|
public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )
|
||||||
{
|
{
|
||||||
if( !(peripheral instanceof PocketSpeakerPeripheral) ) return;
|
if( !(peripheral instanceof PocketSpeakerPeripheral) ) return;
|
||||||
|
((PocketSpeakerPeripheral) peripheral).update();
|
||||||
PocketSpeakerPeripheral speaker = (PocketSpeakerPeripheral) peripheral;
|
|
||||||
|
|
||||||
Entity entity = access.getEntity();
|
|
||||||
if( entity != null )
|
|
||||||
{
|
|
||||||
speaker.setLocation( entity.getCommandSenderWorld(), entity.getEyePosition( 1 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
speaker.update();
|
|
||||||
access.setLight( speaker.madeSound() ? 0x3320fc : -1 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,10 @@
|
|||||||
package dan200.computercraft.shared.pocket.peripherals;
|
package dan200.computercraft.shared.pocket.peripherals;
|
||||||
|
|
||||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||||
import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral;
|
import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
@ -14,26 +17,21 @@ import javax.annotation.Nonnull;
|
|||||||
|
|
||||||
public class PocketSpeakerPeripheral extends UpgradeSpeakerPeripheral
|
public class PocketSpeakerPeripheral extends UpgradeSpeakerPeripheral
|
||||||
{
|
{
|
||||||
private World world = null;
|
private final IPocketAccess access;
|
||||||
|
private World level;
|
||||||
private Vector3d position = Vector3d.ZERO;
|
private Vector3d position = Vector3d.ZERO;
|
||||||
|
|
||||||
void setLocation( World world, Vector3d position )
|
public PocketSpeakerPeripheral( IPocketAccess access )
|
||||||
{
|
{
|
||||||
this.position = position;
|
this.access = access;
|
||||||
this.world = world;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public World getWorld()
|
|
||||||
{
|
|
||||||
return world;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Vector3d getPosition()
|
public SpeakerPosition getPosition()
|
||||||
{
|
{
|
||||||
return world != null ? position : null;
|
Entity entity = access.getEntity();
|
||||||
|
return entity == null ? SpeakerPosition.of( level, position ) : SpeakerPosition.of( entity );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,4 +39,19 @@ public class PocketSpeakerPeripheral extends UpgradeSpeakerPeripheral
|
|||||||
{
|
{
|
||||||
return other instanceof PocketSpeakerPeripheral;
|
return other instanceof PocketSpeakerPeripheral;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update()
|
||||||
|
{
|
||||||
|
Entity entity = access.getEntity();
|
||||||
|
if( entity != null )
|
||||||
|
{
|
||||||
|
level = entity.level;
|
||||||
|
position = entity.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.update();
|
||||||
|
|
||||||
|
access.setLight( madeSound() ? 0x3320fc : -1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,11 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
|
|||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
||||||
import dan200.computercraft.shared.Registry;
|
import dan200.computercraft.shared.Registry;
|
||||||
|
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||||
import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral;
|
import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral;
|
||||||
import net.minecraft.client.renderer.model.ModelResourceLocation;
|
import net.minecraft.client.renderer.model.ModelResourceLocation;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
import net.minecraft.world.World;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
@ -36,17 +36,11 @@ public class TurtleSpeaker extends AbstractTurtleUpgrade
|
|||||||
this.turtle = turtle;
|
this.turtle = turtle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public World getWorld()
|
|
||||||
{
|
|
||||||
return turtle.getWorld();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Vector3d getPosition()
|
public SpeakerPosition getPosition()
|
||||||
{
|
{
|
||||||
return Vector3d.atCenterOf( turtle.getPosition() );
|
return SpeakerPosition.of( turtle.getWorld(), Vector3d.atCenterOf( turtle.getPosition() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user