Skip to content

Commit 0fc1b8c

Browse files
committed
Merge pull request dan200#578 from SquidDev-CC/ComputerCraft/feature/speaker-sound
Change speakers to use the SPacketCustomSound packet instead
2 parents 63ca8ac + e7c19bc commit 0fc1b8c

File tree

1 file changed

+56
-76
lines changed

1 file changed

+56
-76
lines changed

src/main/java/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java

Lines changed: 56 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88

99
import dan200.computercraft.ComputerCraft;
1010
import dan200.computercraft.api.lua.ILuaContext;
11-
import dan200.computercraft.api.lua.ILuaTask;
1211
import dan200.computercraft.api.lua.LuaException;
1312
import dan200.computercraft.api.peripheral.IComputerAccess;
1413
import dan200.computercraft.api.peripheral.IPeripheral;
14+
import net.minecraft.network.play.server.SPacketCustomSound;
15+
import net.minecraft.server.MinecraftServer;
1516
import net.minecraft.util.ResourceLocation;
1617
import net.minecraft.util.SoundCategory;
1718
import net.minecraft.util.SoundEvent;
@@ -25,22 +26,23 @@
2526
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
2627
import static dan200.computercraft.core.apis.ArgumentHelper.optReal;
2728

28-
public class SpeakerPeripheral implements IPeripheral {
29-
private TileSpeaker m_speaker;
29+
public class SpeakerPeripheral implements IPeripheral
30+
{
31+
private final TileSpeaker m_speaker;
3032
private long m_clock;
3133
private long m_lastPlayTime;
3234
private final AtomicInteger m_notesThisTick;
3335

3436
public SpeakerPeripheral()
3537
{
36-
m_clock = 0;
37-
m_lastPlayTime = 0;
38-
m_notesThisTick = new AtomicInteger( );
38+
this( null );
3939
}
4040

41-
SpeakerPeripheral(TileSpeaker speaker)
41+
SpeakerPeripheral( TileSpeaker speaker )
4242
{
43-
this();
43+
m_clock = 0;
44+
m_lastPlayTime = 0;
45+
m_notesThisTick = new AtomicInteger( );
4446
m_speaker = speaker;
4547
}
4648

@@ -70,15 +72,9 @@ public boolean madeSound(long ticks)
7072
@Override
7173
public boolean equals( IPeripheral other )
7274
{
73-
if( other != null && other instanceof SpeakerPeripheral )
74-
{
75-
SpeakerPeripheral otherSpeaker = (SpeakerPeripheral) other;
76-
return otherSpeaker.m_speaker == m_speaker;
77-
}
78-
else
79-
{
80-
return false;
81-
}
75+
if( other == this ) return true;
76+
if( !(other instanceof SpeakerPeripheral) ) return false;
77+
return m_speaker == ((SpeakerPeripheral) other).m_speaker;
8278
}
8379

8480
@Nonnull
@@ -93,8 +89,8 @@ public String getType()
9389
public String[] getMethodNames()
9490
{
9591
return new String[] {
96-
"playSound", // Plays sound at resourceLocator
97-
"playNote" // Plays note
92+
"playSound", // Plays sound at resourceLocator
93+
"playNote" // Plays note
9894
};
9995
}
10096

@@ -106,18 +102,22 @@ public Object[] callMethod( @Nonnull IComputerAccess computerAccess, @Nonnull IL
106102
// playSound
107103
case 0:
108104
{
109-
return playSound(args, context, false);
105+
String name = getString( args, 0 );
106+
float volume = (float) optReal( args, 1, 1.0 );
107+
float pitch = (float) optReal( args, 2, 1.0 );
108+
109+
return new Object[] { playSound( context, name, volume, pitch, false ) };
110110
}
111111

112112
// playNote
113113
case 1:
114114
{
115-
return playNote(args, context);
115+
return playNote( args, context );
116116
}
117117

118118
default:
119119
{
120-
throw new LuaException("Method index out of range!");
120+
throw new LuaException( "Method index out of range!" );
121121
}
122122

123123
}
@@ -126,75 +126,55 @@ public Object[] callMethod( @Nonnull IComputerAccess computerAccess, @Nonnull IL
126126
@Nonnull
127127
private synchronized Object[] playNote( Object[] arguments, ILuaContext context ) throws LuaException
128128
{
129-
String name = getString(arguments, 0);
129+
String name = getString( arguments, 0 );
130130
float volume = (float) optReal( arguments, 1, 1.0 );
131131
float pitch = (float) optReal( arguments, 2, 1.0 );
132+
133+
String noteName = "block.note." + name;
132134

133-
// Check if sound exists
134-
if ( !SoundEvent.REGISTRY.containsKey( new ResourceLocation( "block.note." + name ) ) )
135+
// Check if the note exists
136+
if( !SoundEvent.REGISTRY.containsKey( new ResourceLocation( noteName ) ) )
135137
{
136-
throw new LuaException("Invalid instrument, \"" + arguments[0] + "\"!");
138+
throw new LuaException( "Invalid instrument, \"" + name + "\"!" );
137139
}
138140

139141
// If the resource location for note block notes changes, this method call will need to be updated
140-
Object[] returnValue = playSound(
141-
new Object[] {
142-
"block.note." + name,
143-
(double)Math.min( volume, 3f ),
144-
Math.pow( 2.0f, ( pitch - 12.0f ) / 12.0f)
145-
}, context, true
142+
boolean success = playSound( context, noteName,
143+
Math.min( volume, 3f ),
144+
(float) Math.pow( 2.0, (pitch - 12.0) / 12.0 ), true
146145
);
147146

148-
if( returnValue[0] instanceof Boolean && (Boolean) returnValue[0] )
147+
if( success ) m_notesThisTick.incrementAndGet();
148+
return new Object[] { success };
149+
}
150+
151+
private synchronized boolean playSound( ILuaContext context, String name, float volume, float pitch, boolean isNote ) throws LuaException
152+
{
153+
if( m_clock - m_lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS &&
154+
(!isNote || m_clock - m_lastPlayTime != 0 || m_notesThisTick.get() >= ComputerCraft.maxNotesPerTick) )
149155
{
150-
m_notesThisTick.incrementAndGet();
156+
// Rate limiting occurs when we've already played a sound within the last tick, or we've
157+
// played more notes than allowable within the current tick.
158+
return false;
151159
}
152160

153-
return returnValue;
154-
}
161+
final World world = getWorld();
162+
final BlockPos pos = getPos();
155163

156-
@Nonnull
157-
private synchronized Object[] playSound( Object[] arguments, ILuaContext context, boolean isNote ) throws LuaException
158-
{
159-
String name = getString(arguments, 0);
160-
float volume = (float) optReal( arguments, 1, 1.0 );
161-
float pitch = (float) optReal( arguments, 2, 1.0 );
164+
context.issueMainThreadTask( () -> {
165+
MinecraftServer server = world.getMinecraftServer();
166+
if( server == null ) return null;
162167

163-
ResourceLocation resourceName = new ResourceLocation( name );
168+
double x = pos.getX() + 0.5, y = pos.getY() + 0.5, z = pos.getZ() + 0.5;
169+
server.getPlayerList().sendToAllNearExcept(
170+
null, x, y, z, volume > 1.0f ? 16 * volume : 16.0, world.provider.getDimension(),
171+
new SPacketCustomSound( name, SoundCategory.RECORDS, x, y, z, volume, pitch )
172+
);
173+
return null;
174+
} );
164175

165-
if( m_clock - m_lastPlayTime >= TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS || (isNote && m_clock - m_lastPlayTime == 0 && m_notesThisTick.get() < ComputerCraft.maxNotesPerTick) )
166-
{
167-
if( SoundEvent.REGISTRY.containsKey(resourceName) )
168-
{
169-
final World world = getWorld();
170-
final BlockPos pos = getPos();
171-
final ResourceLocation resource = resourceName;
172-
final float vol = volume;
173-
final float soundPitch = pitch;
174-
175-
context.issueMainThreadTask(new ILuaTask()
176-
{
177-
@Nullable
178-
@Override
179-
public Object[] execute()
180-
{
181-
world.playSound( null, pos, SoundEvent.REGISTRY.getObject( resource ), SoundCategory.RECORDS, Math.min( vol, 3f ), soundPitch );
182-
return null;
183-
}
184-
});
185-
186-
m_lastPlayTime = m_clock;
187-
return new Object[]{true}; // Success, return true
188-
}
189-
else
190-
{
191-
return new Object[]{false}; // Failed - sound not existent, return false
192-
}
193-
}
194-
else
195-
{
196-
return new Object[]{false}; // Failed - rate limited, return false
197-
}
176+
m_lastPlayTime = m_clock;
177+
return true;
198178
}
199179
}
200180

0 commit comments

Comments
 (0)