1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-23 07:26:58 +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 
This commit is contained in:
Jonathan Coates 2022-04-28 19:54:28 +01:00
parent 118b89ea41
commit 9cb7a5bec7
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
13 changed files with 229 additions and 111 deletions

View File

@ -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 );
} }

View File

@ -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 );

View File

@ -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

View File

@ -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 );
} }
} }

View File

@ -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() );
} }
} }

View File

@ -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 );
} }
} }

View File

@ -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(); // TODO: What to do when entities move away? How do we notify people left behind that they're gone.
if( lastPosition.distanceToSqr( position ) >= 0.1 ) NetworkHandler.sendToAllTracking(
{ new SpeakerMoveClientMessage( getSource(), position ),
NetworkHandler.sendToAllTracking( level.getChunkAt( new BlockPos( pos ) )
new SpeakerMoveClientMessage( getSource(), position ), );
getWorld().getChunkAt( new BlockPos( position ) ) 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;

View File

@ -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
);
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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 );
} }
} }

View File

@ -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 );
}
} }

View File

@ -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