1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-03-05 02:58:12 +00:00

Change speakers to use the SPacketCustomSound packet instead

The method to register new SoundEvents is private, which means that few
(if any) mods actually register them. Consequently, one could not use
the speaker to play any modded sound, as they weren't registered on the
server side.

Using SPacketCustomSound does mean we can no longer determine if a sound
exists or not, but I think a price I'm willing to pay in order to allow
playing modded sounds.
This commit is contained in:
SquidDev 2018-10-10 08:46:30 +01:00
parent 914df8b0c7
commit e7c19bcf55

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;
@ -19,27 +20,27 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
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 int m_notesThisTick; private int m_notesThisTick;
public SpeakerPeripheral() public SpeakerPeripheral()
{ {
m_clock = 0; this( null );
m_lastPlayTime = 0;
m_notesThisTick = 0;
} }
SpeakerPeripheral( TileSpeaker speaker ) SpeakerPeripheral( TileSpeaker speaker )
{ {
this(); m_clock = 0;
m_lastPlayTime = 0;
m_notesThisTick = 0;
m_speaker = speaker; m_speaker = speaker;
} }
@ -64,15 +65,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
@ -100,7 +95,11 @@ 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
@ -124,71 +123,51 @@ public class SpeakerPeripheral implements IPeripheral {
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 );
// Check if sound exists String noteName = "block.note." + name;
if ( !SoundEvent.REGISTRY.containsKey( new ResourceLocation( "block.note." + name ) ) )
// Check if the note exists
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++;
{ return new Object[] { success };
m_notesThisTick++;
} }
return returnValue; private synchronized boolean playSound( ILuaContext context, String name, float volume, float pitch, boolean isNote ) throws LuaException
{
if( m_clock - m_lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS &&
(!isNote || m_clock - m_lastPlayTime != 0 || m_notesThisTick >= ComputerCraft.maxNotesPerTick) )
{
// 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.
return false;
} }
@Nonnull
private synchronized Object[] playSound( Object[] arguments, ILuaContext context, boolean isNote ) throws LuaException
{
String name = getString(arguments, 0);
float volume = (float) optReal( arguments, 1, 1.0 );
float pitch = (float) optReal( arguments, 2, 1.0 );
ResourceLocation resourceName = new ResourceLocation( name );
if( m_clock - m_lastPlayTime >= TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS || ( ( m_clock - m_lastPlayTime == 0 ) && ( m_notesThisTick < ComputerCraft.maxNotesPerTick ) && isNote ) )
{
if( SoundEvent.REGISTRY.containsKey(resourceName) )
{
final World world = getWorld(); final World world = getWorld();
final BlockPos pos = getPos(); final BlockPos pos = getPos();
final ResourceLocation resource = resourceName;
final float vol = volume;
final float soundPitch = pitch;
context.issueMainThreadTask(new ILuaTask() context.issueMainThreadTask( () -> {
{ MinecraftServer server = world.getMinecraftServer();
@Nullable if( server == null ) return null;
@Override
public Object[] execute() throws LuaException double x = pos.getX() + 0.5, y = pos.getY() + 0.5, z = pos.getZ() + 0.5;
{ server.getPlayerList().sendToAllNearExcept(
world.playSound( null, pos, SoundEvent.REGISTRY.getObject( resource ), SoundCategory.RECORDS, Math.min( vol, 3f ), soundPitch ); 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; return null;
}
} ); } );
m_lastPlayTime = m_clock; m_lastPlayTime = m_clock;
return new Object[]{true}; // Success, return true return true;
}
else
{
return new Object[]{false}; // Failed - sound not existent, return false
}
}
else
{
return new Object[]{false}; // Failed - rate limited, return false
}
} }
} }