1
0
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:
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();
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;

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