1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-12 10:20:28 +00:00

Merge pull request #578 from SquidDev-CC/ComputerCraft/feature/speaker-sound

Change speakers to use the SPacketCustomSound packet instead
This commit is contained in:
SquidDev 2018-10-10 16:57:34 +01:00
commit 0fc1b8c46b

View File

@ -8,10 +8,11 @@ package dan200.computercraft.shared.peripheral.speaker;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.network.play.server.SPacketCustomSound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvent;
@ -25,22 +26,23 @@ import java.util.concurrent.atomic.AtomicInteger;
import static dan200.computercraft.core.apis.ArgumentHelper.getString; import static dan200.computercraft.core.apis.ArgumentHelper.getString;
import static dan200.computercraft.core.apis.ArgumentHelper.optReal; import static dan200.computercraft.core.apis.ArgumentHelper.optReal;
public class SpeakerPeripheral implements IPeripheral { public class SpeakerPeripheral implements IPeripheral
private TileSpeaker m_speaker; {
private final TileSpeaker m_speaker;
private long m_clock; private long m_clock;
private long m_lastPlayTime; private long m_lastPlayTime;
private final AtomicInteger m_notesThisTick; private final AtomicInteger m_notesThisTick;
public SpeakerPeripheral() public SpeakerPeripheral()
{
this( null );
}
SpeakerPeripheral( TileSpeaker speaker )
{ {
m_clock = 0; m_clock = 0;
m_lastPlayTime = 0; m_lastPlayTime = 0;
m_notesThisTick = new AtomicInteger( ); m_notesThisTick = new AtomicInteger( );
}
SpeakerPeripheral(TileSpeaker speaker)
{
this();
m_speaker = speaker; m_speaker = speaker;
} }
@ -70,15 +72,9 @@ public class SpeakerPeripheral implements IPeripheral {
@Override @Override
public boolean equals( IPeripheral other ) public boolean equals( IPeripheral other )
{ {
if( other != null && other instanceof SpeakerPeripheral ) if( other == this ) return true;
{ if( !(other instanceof SpeakerPeripheral) ) return false;
SpeakerPeripheral otherSpeaker = (SpeakerPeripheral) other; return m_speaker == ((SpeakerPeripheral) other).m_speaker;
return otherSpeaker.m_speaker == m_speaker;
}
else
{
return false;
}
} }
@Nonnull @Nonnull
@ -93,8 +89,8 @@ public class SpeakerPeripheral implements IPeripheral {
public String[] getMethodNames() public String[] getMethodNames()
{ {
return new String[] { return new String[] {
"playSound", // Plays sound at resourceLocator "playSound", // Plays sound at resourceLocator
"playNote" // Plays note "playNote" // Plays note
}; };
} }
@ -106,18 +102,22 @@ public class SpeakerPeripheral implements IPeripheral {
// playSound // playSound
case 0: case 0:
{ {
return playSound(args, context, false); String name = getString( args, 0 );
float volume = (float) optReal( args, 1, 1.0 );
float pitch = (float) optReal( args, 2, 1.0 );
return new Object[] { playSound( context, name, volume, pitch, false ) };
} }
// playNote // playNote
case 1: case 1:
{ {
return playNote(args, context); return playNote( args, context );
} }
default: default:
{ {
throw new LuaException("Method index out of range!"); throw new LuaException( "Method index out of range!" );
} }
} }
@ -126,75 +126,55 @@ public class SpeakerPeripheral implements IPeripheral {
@Nonnull @Nonnull
private synchronized Object[] playNote( Object[] arguments, ILuaContext context ) throws LuaException private synchronized Object[] playNote( Object[] arguments, ILuaContext context ) throws LuaException
{ {
String name = getString(arguments, 0); String name = getString( arguments, 0 );
float volume = (float) optReal( arguments, 1, 1.0 ); float volume = (float) optReal( arguments, 1, 1.0 );
float pitch = (float) optReal( arguments, 2, 1.0 ); float pitch = (float) optReal( arguments, 2, 1.0 );
String noteName = "block.note." + name;
// Check if sound exists // Check if the note exists
if ( !SoundEvent.REGISTRY.containsKey( new ResourceLocation( "block.note." + name ) ) ) if( !SoundEvent.REGISTRY.containsKey( new ResourceLocation( noteName ) ) )
{ {
throw new LuaException("Invalid instrument, \"" + arguments[0] + "\"!"); throw new LuaException( "Invalid instrument, \"" + name + "\"!" );
} }
// If the resource location for note block notes changes, this method call will need to be updated // If the resource location for note block notes changes, this method call will need to be updated
Object[] returnValue = playSound( boolean success = playSound( context, noteName,
new Object[] { Math.min( volume, 3f ),
"block.note." + name, (float) Math.pow( 2.0, (pitch - 12.0) / 12.0 ), true
(double)Math.min( volume, 3f ),
Math.pow( 2.0f, ( pitch - 12.0f ) / 12.0f)
}, context, true
); );
if( returnValue[0] instanceof Boolean && (Boolean) returnValue[0] ) if( success ) m_notesThisTick.incrementAndGet();
{ return new Object[] { success };
m_notesThisTick.incrementAndGet();
}
return returnValue;
} }
@Nonnull private synchronized boolean playSound( ILuaContext context, String name, float volume, float pitch, boolean isNote ) throws LuaException
private synchronized Object[] playSound( Object[] arguments, ILuaContext context, boolean isNote ) throws LuaException
{ {
String name = getString(arguments, 0); if( m_clock - m_lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS &&
float volume = (float) optReal( arguments, 1, 1.0 ); (!isNote || m_clock - m_lastPlayTime != 0 || m_notesThisTick.get() >= ComputerCraft.maxNotesPerTick) )
float pitch = (float) optReal( arguments, 2, 1.0 );
ResourceLocation resourceName = new ResourceLocation( name );
if( m_clock - m_lastPlayTime >= TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS || (isNote && m_clock - m_lastPlayTime == 0 && m_notesThisTick.get() < ComputerCraft.maxNotesPerTick) )
{ {
if( SoundEvent.REGISTRY.containsKey(resourceName) ) // Rate limiting occurs when we've already played a sound within the last tick, or we've
{ // played more notes than allowable within the current tick.
final World world = getWorld(); return false;
final BlockPos pos = getPos();
final ResourceLocation resource = resourceName;
final float vol = volume;
final float soundPitch = pitch;
context.issueMainThreadTask(new ILuaTask()
{
@Nullable
@Override
public Object[] execute()
{
world.playSound( null, pos, SoundEvent.REGISTRY.getObject( resource ), SoundCategory.RECORDS, Math.min( vol, 3f ), soundPitch );
return null;
}
});
m_lastPlayTime = m_clock;
return new Object[]{true}; // Success, return true
}
else
{
return new Object[]{false}; // Failed - sound not existent, return false
}
}
else
{
return new Object[]{false}; // Failed - rate limited, return false
} }
final World world = getWorld();
final BlockPos pos = getPos();
context.issueMainThreadTask( () -> {
MinecraftServer server = world.getMinecraftServer();
if( server == null ) return null;
double x = pos.getX() + 0.5, y = pos.getY() + 0.5, z = pos.getZ() + 0.5;
server.getPlayerList().sendToAllNearExcept(
null, x, y, z, volume > 1.0f ? 16 * volume : 16.0, world.provider.getDimension(),
new SPacketCustomSound( name, SoundCategory.RECORDS, x, y, z, volume, pitch )
);
return null;
} );
m_lastPlayTime = m_clock;
return true;
} }
} }