mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 13:42:59 +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:
		| @@ -6,11 +6,11 @@ | ||||
| package dan200.computercraft.client.sound; | ||||
| 
 | ||||
| import dan200.computercraft.ComputerCraft; | ||||
| import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; | ||||
| import io.netty.buffer.ByteBuf; | ||||
| import net.minecraft.client.Minecraft; | ||||
| import net.minecraft.client.audio.SoundHandler; | ||||
| 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. | ||||
| @@ -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(); | ||||
| 
 | ||||
| @@ -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(); | ||||
|         currentStream = null; | ||||
| @@ -78,7 +78,7 @@ public class SpeakerInstance | ||||
|         soundManager.play( sound ); | ||||
|     } | ||||
| 
 | ||||
|     void setPosition( Vector3d position ) | ||||
|     void setPosition( SpeakerPosition position ) | ||||
|     { | ||||
|         if( sound != null ) sound.setPosition( position ); | ||||
|     } | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
|  */ | ||||
| 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.client.event.sound.PlayStreamingSourceEvent; | ||||
| import net.minecraftforge.eventbus.api.SubscribeEvent; | ||||
| @@ -48,7 +48,7 @@ public class SpeakerManager | ||||
|         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 ); | ||||
|         if( sound != null ) sound.setPosition( position ); | ||||
|   | ||||
| @@ -5,13 +5,14 @@ | ||||
|  */ | ||||
| package dan200.computercraft.client.sound; | ||||
| 
 | ||||
| import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; | ||||
| import net.minecraft.client.audio.IAudioStream; | ||||
| import net.minecraft.client.audio.ITickableSound; | ||||
| import net.minecraft.client.audio.LocatableSound; | ||||
| import net.minecraft.client.audio.SoundSource; | ||||
| import net.minecraft.entity.Entity; | ||||
| import net.minecraft.util.ResourceLocation; | ||||
| import net.minecraft.util.SoundCategory; | ||||
| import net.minecraft.util.math.vector.Vector3d; | ||||
| 
 | ||||
| import javax.annotation.Nullable; | ||||
| import java.util.concurrent.Executor; | ||||
| @@ -22,7 +23,11 @@ public class SpeakerSound extends LocatableSound implements ITickableSound | ||||
|     Executor executor; | ||||
|     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 ); | ||||
|         setPosition( position ); | ||||
| @@ -32,22 +37,35 @@ public class SpeakerSound extends LocatableSound implements ITickableSound | ||||
|         attenuation = AttenuationType.LINEAR; | ||||
|     } | ||||
| 
 | ||||
|     void setPosition( Vector3d position ) | ||||
|     void setPosition( SpeakerPosition position ) | ||||
|     { | ||||
|         x = (float) position.x(); | ||||
|         y = (float) position.y(); | ||||
|         z = (float) position.z(); | ||||
|         x = position.position().x; | ||||
|         y = position.position().y; | ||||
|         z = position.position().z; | ||||
|         entity = position.entity(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isStopped() | ||||
|     { | ||||
|         return false; | ||||
|         return stopped; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     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 | ||||
|   | ||||
| @@ -7,8 +7,8 @@ package dan200.computercraft.shared.network.client; | ||||
| 
 | ||||
| import dan200.computercraft.client.sound.SpeakerManager; | ||||
| import dan200.computercraft.shared.network.NetworkMessage; | ||||
| import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; | ||||
| import net.minecraft.network.PacketBuffer; | ||||
| import net.minecraft.util.math.vector.Vector3d; | ||||
| import net.minecraftforge.api.distmarker.Dist; | ||||
| import net.minecraftforge.api.distmarker.OnlyIn; | ||||
| import net.minecraftforge.fml.network.NetworkEvent; | ||||
| @@ -27,14 +27,14 @@ import java.util.UUID; | ||||
| public class SpeakerAudioClientMessage implements NetworkMessage | ||||
| { | ||||
|     private final UUID source; | ||||
|     private final Vector3d pos; | ||||
|     private final SpeakerPosition.Message pos; | ||||
|     private final ByteBuffer content; | ||||
|     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.pos = pos; | ||||
|         this.pos = pos.asMessage(); | ||||
|         this.content = content; | ||||
|         this.volume = volume; | ||||
|     } | ||||
| @@ -42,7 +42,7 @@ public class SpeakerAudioClientMessage implements NetworkMessage | ||||
|     public SpeakerAudioClientMessage( PacketBuffer buf ) | ||||
|     { | ||||
|         source = buf.readUUID(); | ||||
|         pos = new Vector3d( buf.readDouble(), buf.readDouble(), buf.readDouble() ); | ||||
|         pos = SpeakerPosition.Message.read( buf ); | ||||
|         volume = buf.readFloat(); | ||||
| 
 | ||||
|         SpeakerManager.getSound( source ).pushAudio( buf ); | ||||
| @@ -53,9 +53,7 @@ public class SpeakerAudioClientMessage implements NetworkMessage | ||||
|     public void toBytes( @Nonnull PacketBuffer buf ) | ||||
|     { | ||||
|         buf.writeUUID( source ); | ||||
|         buf.writeDouble( pos.x() ); | ||||
|         buf.writeDouble( pos.y() ); | ||||
|         buf.writeDouble( pos.z() ); | ||||
|         pos.write( buf ); | ||||
|         buf.writeFloat( volume ); | ||||
|         buf.writeBytes( content.duplicate() ); | ||||
|     } | ||||
| @@ -64,6 +62,6 @@ public class SpeakerAudioClientMessage implements NetworkMessage | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     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.shared.network.NetworkMessage; | ||||
| import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; | ||||
| import net.minecraft.network.PacketBuffer; | ||||
| import net.minecraft.util.math.vector.Vector3d; | ||||
| import net.minecraftforge.api.distmarker.Dist; | ||||
| import net.minecraftforge.api.distmarker.OnlyIn; | ||||
| import net.minecraftforge.fml.network.NetworkEvent; | ||||
| @@ -26,33 +26,31 @@ import java.util.UUID; | ||||
| public class SpeakerMoveClientMessage implements NetworkMessage | ||||
| { | ||||
|     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.pos = pos; | ||||
|         this.pos = pos.asMessage(); | ||||
|     } | ||||
| 
 | ||||
|     public SpeakerMoveClientMessage( PacketBuffer buf ) | ||||
|     { | ||||
|         source = buf.readUUID(); | ||||
|         pos = new Vector3d( buf.readDouble(), buf.readDouble(), buf.readDouble() ); | ||||
|         pos = SpeakerPosition.Message.read( buf ); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void toBytes( @Nonnull PacketBuffer buf ) | ||||
|     { | ||||
|         buf.writeUUID( source ); | ||||
|         buf.writeDouble( pos.x() ); | ||||
|         buf.writeDouble( pos.y() ); | ||||
|         buf.writeDouble( pos.z() ); | ||||
|         pos.write( buf ); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     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.shared.network.NetworkMessage; | ||||
| import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; | ||||
| import net.minecraft.network.PacketBuffer; | ||||
| import net.minecraft.util.ResourceLocation; | ||||
| import net.minecraft.util.math.vector.Vector3d; | ||||
| import net.minecraftforge.api.distmarker.Dist; | ||||
| import net.minecraftforge.api.distmarker.OnlyIn; | ||||
| import net.minecraftforge.fml.network.NetworkEvent; | ||||
| @@ -27,15 +27,15 @@ import java.util.UUID; | ||||
| public class SpeakerPlayClientMessage implements NetworkMessage | ||||
| { | ||||
|     private final UUID source; | ||||
|     private final Vector3d pos; | ||||
|     private final SpeakerPosition.Message pos; | ||||
|     private final ResourceLocation sound; | ||||
|     private final float volume; | ||||
|     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.pos = pos; | ||||
|         this.pos = pos.asMessage(); | ||||
|         sound = event; | ||||
|         this.volume = volume; | ||||
|         this.pitch = pitch; | ||||
| @@ -44,7 +44,7 @@ public class SpeakerPlayClientMessage implements NetworkMessage | ||||
|     public SpeakerPlayClientMessage( PacketBuffer buf ) | ||||
|     { | ||||
|         source = buf.readUUID(); | ||||
|         pos = new Vector3d( buf.readDouble(), buf.readDouble(), buf.readDouble() ); | ||||
|         pos = SpeakerPosition.Message.read( buf ); | ||||
|         sound = buf.readResourceLocation(); | ||||
|         volume = buf.readFloat(); | ||||
|         pitch = buf.readFloat(); | ||||
| @@ -54,9 +54,7 @@ public class SpeakerPlayClientMessage implements NetworkMessage | ||||
|     public void toBytes( @Nonnull PacketBuffer buf ) | ||||
|     { | ||||
|         buf.writeUUID( source ); | ||||
|         buf.writeDouble( pos.x() ); | ||||
|         buf.writeDouble( pos.y() ); | ||||
|         buf.writeDouble( pos.z() ); | ||||
|         pos.write( buf ); | ||||
|         buf.writeResourceLocation( sound ); | ||||
|         buf.writeFloat( volume ); | ||||
|         buf.writeFloat( pitch ); | ||||
| @@ -66,6 +64,6 @@ public class SpeakerPlayClientMessage implements NetworkMessage | ||||
|     @OnlyIn( Dist.CLIENT ) | ||||
|     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 javax.annotation.Nonnull; | ||||
| import javax.annotation.Nullable; | ||||
| import java.util.*; | ||||
| 
 | ||||
| import static dan200.computercraft.api.lua.LuaValues.checkFinite; | ||||
| @@ -57,7 +56,7 @@ public abstract class SpeakerPeripheral implements IPeripheral | ||||
| 
 | ||||
|     private long clock = 0; | ||||
|     private long lastPositionTime; | ||||
|     private Vector3d lastPosition; | ||||
|     private SpeakerPosition lastPosition; | ||||
| 
 | ||||
|     private long lastPlayTime; | ||||
| 
 | ||||
| @@ -72,10 +71,11 @@ public abstract class SpeakerPeripheral implements IPeripheral | ||||
|     { | ||||
|         clock++; | ||||
| 
 | ||||
|         Vector3d pos = getPosition(); | ||||
|         World world = getWorld(); | ||||
|         if( world == null ) return; | ||||
|         MinecraftServer server = world.getServer(); | ||||
|         SpeakerPosition position = getPosition(); | ||||
|         World level = position.level(); | ||||
|         Vector3d pos = position.position(); | ||||
|         if( level == null ) return; | ||||
|         MinecraftServer server = level.getServer(); | ||||
| 
 | ||||
|         synchronized( pendingNotes ) | ||||
|         { | ||||
| @@ -83,7 +83,7 @@ public abstract class SpeakerPeripheral implements IPeripheral | ||||
|             { | ||||
|                 lastPlayTime = clock; | ||||
|                 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 ) | ||||
|                 ); | ||||
|             } | ||||
| @@ -125,20 +125,20 @@ public abstract class SpeakerPeripheral implements IPeripheral | ||||
|         { | ||||
|             lastPlayTime = clock; | ||||
|             NetworkHandler.sendToAllAround( | ||||
|                 new SpeakerPlayClientMessage( getSource(), pos, sound.location, sound.volume, sound.pitch ), | ||||
|                 world, pos, sound.volume * 16 | ||||
|                 new SpeakerPlayClientMessage( getSource(), position, sound.location, sound.volume, sound.pitch ), | ||||
|                 level, pos, sound.volume * 16 | ||||
|             ); | ||||
|             syncedPosition( pos ); | ||||
|             syncedPosition( position ); | ||||
|         } | ||||
|         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 | ||||
|             // free again. | ||||
|             NetworkHandler.sendToAllTracking( | ||||
|                 new SpeakerAudioClientMessage( getSource(), pos, dfpwmState.getVolume(), dfpwmState.pullPending( now ) ), | ||||
|                 getWorld().getChunkAt( new BlockPos( pos ) ) | ||||
|                 new SpeakerAudioClientMessage( getSource(), position, dfpwmState.getVolume(), dfpwmState.pullPending( now ) ), | ||||
|                 level.getChunkAt( new BlockPos( pos ) ) | ||||
|             ); | ||||
|             syncedPosition( pos ); | ||||
|             syncedPosition( position ); | ||||
| 
 | ||||
|             // And notify computers that we have space for more audio. | ||||
|             synchronized( computers ) | ||||
| @@ -153,25 +153,19 @@ public abstract class SpeakerPeripheral implements IPeripheral | ||||
|         // 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 | ||||
|         // in the last second. | ||||
|         if( lastPosition != null && (clock - lastPositionTime) >= 20 ) | ||||
|         { | ||||
|             Vector3d position = getPosition(); | ||||
|             if( lastPosition.distanceToSqr( position ) >= 0.1 ) | ||||
|         if( lastPosition != null && (clock - lastPositionTime) >= 20 && !lastPosition.withinDistance( position, 0.1 ) ) | ||||
|         { | ||||
|             // TODO: What to do when entities move away? How do we notify people left behind that they're gone. | ||||
|             NetworkHandler.sendToAllTracking( | ||||
|                 new SpeakerMoveClientMessage( getSource(), position ), | ||||
|                     getWorld().getChunkAt( new BlockPos( position ) ) | ||||
|                 level.getChunkAt( new BlockPos( pos ) ) | ||||
|             ); | ||||
|             syncedPosition( position ); | ||||
|         } | ||||
|     } | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     public abstract World getWorld(); | ||||
| 
 | ||||
|     @Nonnull | ||||
|     public abstract Vector3d getPosition(); | ||||
|     public abstract SpeakerPosition getPosition(); | ||||
| 
 | ||||
|     @Nonnull | ||||
|     public UUID getSource() | ||||
| @@ -373,7 +367,7 @@ public abstract class SpeakerPeripheral implements IPeripheral | ||||
|         shouldStop = true; | ||||
|     } | ||||
| 
 | ||||
|     private void syncedPosition( Vector3d position ) | ||||
|     private void syncedPosition( SpeakerPosition position ) | ||||
|     { | ||||
|         lastPosition = position; | ||||
|         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.util.Direction; | ||||
| import net.minecraft.util.math.vector.Vector3d; | ||||
| import net.minecraft.world.World; | ||||
| import net.minecraftforge.common.capabilities.Capability; | ||||
| import net.minecraftforge.common.util.LazyOptional; | ||||
| 
 | ||||
| @@ -79,17 +78,11 @@ public class TileSpeaker extends TileGeneric implements ITickableTileEntity | ||||
|             this.speaker = speaker; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public World getWorld() | ||||
|         { | ||||
|             return speaker.getLevel(); | ||||
|         } | ||||
| 
 | ||||
|         @Nonnull | ||||
|         @Override | ||||
|         public Vector3d getPosition() | ||||
|         public SpeakerPosition getPosition() | ||||
|         { | ||||
|             return Vector3d.atCenterOf( speaker.getBlockPos() ); | ||||
|             return SpeakerPosition.of( speaker.getLevel(), Vector3d.atCenterOf( speaker.getBlockPos() ) ); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|   | ||||
| @@ -17,6 +17,7 @@ import dan200.computercraft.shared.network.NetworkHandler; | ||||
| import dan200.computercraft.shared.pocket.items.ItemPocketComputer; | ||||
| import net.minecraft.entity.Entity; | ||||
| import net.minecraft.entity.LivingEntity; | ||||
| import net.minecraft.entity.item.ItemEntity; | ||||
| import net.minecraft.entity.player.PlayerEntity; | ||||
| import net.minecraft.entity.player.PlayerInventory; | ||||
| import net.minecraft.entity.player.ServerPlayerEntity; | ||||
| @@ -61,6 +62,11 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces | ||||
|             LivingEntity living = (LivingEntity) entity; | ||||
|             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 | ||||
|         { | ||||
|             return null; | ||||
|   | ||||
| @@ -9,7 +9,6 @@ import dan200.computercraft.api.peripheral.IPeripheral; | ||||
| import dan200.computercraft.api.pocket.AbstractPocketUpgrade; | ||||
| import dan200.computercraft.api.pocket.IPocketAccess; | ||||
| import dan200.computercraft.shared.Registry; | ||||
| import net.minecraft.entity.Entity; | ||||
| import net.minecraft.util.ResourceLocation; | ||||
| 
 | ||||
| import javax.annotation.Nonnull; | ||||
| @@ -26,23 +25,13 @@ public class PocketSpeaker extends AbstractPocketUpgrade | ||||
|     @Override | ||||
|     public IPeripheral createPeripheral( @Nonnull IPocketAccess access ) | ||||
|     { | ||||
|         return new PocketSpeakerPeripheral(); | ||||
|         return new PocketSpeakerPeripheral( access ); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) | ||||
|     { | ||||
|         if( !(peripheral instanceof PocketSpeakerPeripheral) ) return; | ||||
| 
 | ||||
|         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 ); | ||||
|         ((PocketSpeakerPeripheral) peripheral).update(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,10 @@ | ||||
| package dan200.computercraft.shared.pocket.peripherals; | ||||
| 
 | ||||
| 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 net.minecraft.entity.Entity; | ||||
| import net.minecraft.util.math.vector.Vector3d; | ||||
| import net.minecraft.world.World; | ||||
| 
 | ||||
| @@ -14,26 +17,21 @@ import javax.annotation.Nonnull; | ||||
| 
 | ||||
| public class PocketSpeakerPeripheral extends UpgradeSpeakerPeripheral | ||||
| { | ||||
|     private World world = null; | ||||
|     private final IPocketAccess access; | ||||
|     private World level; | ||||
|     private Vector3d position = Vector3d.ZERO; | ||||
| 
 | ||||
|     void setLocation( World world, Vector3d position ) | ||||
|     public PocketSpeakerPeripheral( IPocketAccess access ) | ||||
|     { | ||||
|         this.position = position; | ||||
|         this.world = world; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public World getWorld() | ||||
|     { | ||||
|         return world; | ||||
|         this.access = access; | ||||
|     } | ||||
| 
 | ||||
|     @Nonnull | ||||
|     @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 | ||||
| @@ -41,4 +39,19 @@ public class PocketSpeakerPeripheral extends UpgradeSpeakerPeripheral | ||||
|     { | ||||
|         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.TurtleUpgradeType; | ||||
| import dan200.computercraft.shared.Registry; | ||||
| import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition; | ||||
| import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral; | ||||
| import net.minecraft.client.renderer.model.ModelResourceLocation; | ||||
| import net.minecraft.util.ResourceLocation; | ||||
| import net.minecraft.util.math.vector.Vector3d; | ||||
| import net.minecraft.world.World; | ||||
| import net.minecraftforge.api.distmarker.Dist; | ||||
| import net.minecraftforge.api.distmarker.OnlyIn; | ||||
| 
 | ||||
| @@ -36,17 +36,11 @@ public class TurtleSpeaker extends AbstractTurtleUpgrade | ||||
|             this.turtle = turtle; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public World getWorld() | ||||
|         { | ||||
|             return turtle.getWorld(); | ||||
|         } | ||||
| 
 | ||||
|         @Nonnull | ||||
|         @Override | ||||
|         public Vector3d getPosition() | ||||
|         public SpeakerPosition getPosition() | ||||
|         { | ||||
|             return Vector3d.atCenterOf( turtle.getPosition() ); | ||||
|             return SpeakerPosition.of( turtle.getWorld(), Vector3d.atCenterOf( turtle.getPosition() ) ); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates