1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-13 11:40:29 +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.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IComputerAccess;
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.SoundCategory;
import net.minecraft.util.SoundEvent;
@ -19,27 +20,27 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
import static dan200.computercraft.core.apis.ArgumentHelper.optReal;
public class SpeakerPeripheral implements IPeripheral {
private TileSpeaker m_speaker;
public class SpeakerPeripheral implements IPeripheral
{
private final TileSpeaker m_speaker;
private long m_clock;
private long m_lastPlayTime;
private int m_notesThisTick;
public SpeakerPeripheral()
{
this( null );
}
SpeakerPeripheral( TileSpeaker speaker )
{
m_clock = 0;
m_lastPlayTime = 0;
m_notesThisTick = 0;
}
SpeakerPeripheral(TileSpeaker speaker)
{
this();
m_speaker = speaker;
}
@ -64,15 +65,9 @@ public class SpeakerPeripheral implements IPeripheral {
@Override
public boolean equals( IPeripheral other )
{
if( other != null && other instanceof SpeakerPeripheral )
{
SpeakerPeripheral otherSpeaker = (SpeakerPeripheral) other;
return otherSpeaker.m_speaker == m_speaker;
}
else
{
return false;
}
if( other == this ) return true;
if( !(other instanceof SpeakerPeripheral) ) return false;
return m_speaker == ((SpeakerPeripheral) other).m_speaker;
}
@Nonnull
@ -87,8 +82,8 @@ public class SpeakerPeripheral implements IPeripheral {
public String[] getMethodNames()
{
return new String[] {
"playSound", // Plays sound at resourceLocator
"playNote" // Plays note
"playSound", // Plays sound at resourceLocator
"playNote" // Plays note
};
}
@ -100,18 +95,22 @@ public class SpeakerPeripheral implements IPeripheral {
// playSound
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
case 1:
{
return playNote(args, context);
return playNote( args, context );
}
default:
{
throw new LuaException("Method index out of range!");
throw new LuaException( "Method index out of range!" );
}
}
@ -120,75 +119,55 @@ public class SpeakerPeripheral implements IPeripheral {
@Nonnull
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 pitch = (float) optReal( arguments, 2, 1.0 );
String noteName = "block.note." + name;
// Check if sound exists
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
Object[] returnValue = playSound(
new Object[] {
"block.note." + name,
(double)Math.min( volume, 3f ),
Math.pow( 2.0f, ( pitch - 12.0f ) / 12.0f)
}, context, true
boolean success = playSound( context, noteName,
Math.min( volume, 3f ),
(float) Math.pow( 2.0, (pitch - 12.0) / 12.0 ), true
);
if( returnValue[0] instanceof Boolean && (Boolean) returnValue[0] )
{
m_notesThisTick++;
}
return returnValue;
if( success ) m_notesThisTick++;
return new Object[] { success };
}
@Nonnull
private synchronized Object[] playSound( Object[] arguments, ILuaContext context, boolean isNote ) throws LuaException
private synchronized boolean playSound( ILuaContext context, String name, float volume, float pitch, 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( m_clock - m_lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS &&
(!isNote || m_clock - m_lastPlayTime != 0 || m_notesThisTick >= ComputerCraft.maxNotesPerTick) )
{
if( SoundEvent.REGISTRY.containsKey(resourceName) )
{
final World world = getWorld();
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() throws LuaException
{
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
// 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;
}
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;
}
}