88
99import dan200 .computercraft .ComputerCraft ;
1010import dan200 .computercraft .api .lua .ILuaContext ;
11- import dan200 .computercraft .api .lua .ILuaTask ;
1211import dan200 .computercraft .api .lua .LuaException ;
1312import dan200 .computercraft .api .peripheral .IComputerAccess ;
1413import dan200 .computercraft .api .peripheral .IPeripheral ;
14+ import net .minecraft .network .play .server .SPacketCustomSound ;
15+ import net .minecraft .server .MinecraftServer ;
1516import net .minecraft .util .ResourceLocation ;
1617import net .minecraft .util .SoundCategory ;
1718import net .minecraft .util .SoundEvent ;
2526import static dan200 .computercraft .core .apis .ArgumentHelper .getString ;
2627import 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