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 ;
1819import net .minecraft .util .math .BlockPos ;
1920import net .minecraft .world .World ;
2021
2122import javax .annotation .Nonnull ;
22- import javax .annotation .Nullable ;
2323
2424import static dan200 .computercraft .core .apis .ArgumentHelper .getString ;
2525import static dan200 .computercraft .core .apis .ArgumentHelper .optReal ;
2626
27- public class SpeakerPeripheral implements IPeripheral {
28- private TileSpeaker m_speaker ;
27+ public class SpeakerPeripheral implements IPeripheral
28+ {
29+ private final TileSpeaker m_speaker ;
2930 private long m_clock ;
3031 private long m_lastPlayTime ;
3132 private int m_notesThisTick ;
3233
3334 public SpeakerPeripheral ()
3435 {
35- m_clock = 0 ;
36- m_lastPlayTime = 0 ;
37- m_notesThisTick = 0 ;
36+ this ( null );
3837 }
3938
40- SpeakerPeripheral (TileSpeaker speaker )
39+ SpeakerPeripheral ( TileSpeaker speaker )
4140 {
42- this ();
41+ m_clock = 0 ;
42+ m_lastPlayTime = 0 ;
43+ m_notesThisTick = 0 ;
4344 m_speaker = speaker ;
4445 }
4546
@@ -64,15 +65,9 @@ public BlockPos getPos()
6465 @ Override
6566 public boolean equals ( IPeripheral other )
6667 {
67- if ( other != null && other instanceof SpeakerPeripheral )
68- {
69- SpeakerPeripheral otherSpeaker = (SpeakerPeripheral ) other ;
70- return otherSpeaker .m_speaker == m_speaker ;
71- }
72- else
73- {
74- return false ;
75- }
68+ if ( other == this ) return true ;
69+ if ( !(other instanceof SpeakerPeripheral ) ) return false ;
70+ return m_speaker == ((SpeakerPeripheral ) other ).m_speaker ;
7671 }
7772
7873 @ Nonnull
@@ -87,8 +82,8 @@ public String getType()
8782 public String [] getMethodNames ()
8883 {
8984 return new String [] {
90- "playSound" , // Plays sound at resourceLocator
91- "playNote" // Plays note
85+ "playSound" , // Plays sound at resourceLocator
86+ "playNote" // Plays note
9287 };
9388 }
9489
@@ -100,18 +95,22 @@ public Object[] callMethod( @Nonnull IComputerAccess computerAccess, @Nonnull IL
10095 // playSound
10196 case 0 :
10297 {
103- return playSound (args , context , false );
98+ String name = getString ( args , 0 );
99+ float volume = (float ) optReal ( args , 1 , 1.0 );
100+ float pitch = (float ) optReal ( args , 2 , 1.0 );
101+
102+ return new Object [] { playSound ( context , name , volume , pitch , false ) };
104103 }
105104
106105 // playNote
107106 case 1 :
108107 {
109- return playNote (args , context );
108+ return playNote ( args , context );
110109 }
111110
112111 default :
113112 {
114- throw new LuaException ("Method index out of range!" );
113+ throw new LuaException ( "Method index out of range!" );
115114 }
116115
117116 }
@@ -120,75 +119,55 @@ public Object[] callMethod( @Nonnull IComputerAccess computerAccess, @Nonnull IL
120119 @ Nonnull
121120 private synchronized Object [] playNote ( Object [] arguments , ILuaContext context ) throws LuaException
122121 {
123- String name = getString (arguments , 0 );
122+ String name = getString ( arguments , 0 );
124123 float volume = (float ) optReal ( arguments , 1 , 1.0 );
125124 float pitch = (float ) optReal ( arguments , 2 , 1.0 );
125+
126+ String noteName = "block.note." + name ;
126127
127- // Check if sound exists
128- if ( !SoundEvent .REGISTRY .containsKey ( new ResourceLocation ( "block.note." + name ) ) )
128+ // Check if the note exists
129+ if ( !SoundEvent .REGISTRY .containsKey ( new ResourceLocation ( noteName ) ) )
129130 {
130- throw new LuaException ("Invalid instrument, \" " + arguments [ 0 ] + "\" !" );
131+ throw new LuaException ( "Invalid instrument, \" " + name + "\" !" );
131132 }
132133
133134 // If the resource location for note block notes changes, this method call will need to be updated
134- Object [] returnValue = playSound (
135- new Object [] {
136- "block.note." + name ,
137- (double )Math .min ( volume , 3f ),
138- Math .pow ( 2.0f , ( pitch - 12.0f ) / 12.0f )
139- }, context , true
135+ boolean success = playSound ( context , noteName ,
136+ Math .min ( volume , 3f ),
137+ (float ) Math .pow ( 2.0 , (pitch - 12.0 ) / 12.0 ), true
140138 );
141139
142- if ( returnValue [0 ] instanceof Boolean && (Boolean ) returnValue [0 ] )
140+ if ( success ) m_notesThisTick ++;
141+ return new Object [] { success };
142+ }
143+
144+ private synchronized boolean playSound ( ILuaContext context , String name , float volume , float pitch , boolean isNote ) throws LuaException
145+ {
146+ if ( m_clock - m_lastPlayTime < TileSpeaker .MIN_TICKS_BETWEEN_SOUNDS &&
147+ (!isNote || m_clock - m_lastPlayTime != 0 || m_notesThisTick >= ComputerCraft .maxNotesPerTick ) )
143148 {
144- m_notesThisTick ++;
149+ // Rate limiting occurs when we've already played a sound within the last tick, or we've
150+ // played more notes than allowable within the current tick.
151+ return false ;
145152 }
146153
147- return returnValue ;
148- }
154+ final World world = getWorld () ;
155+ final BlockPos pos = getPos ();
149156
150- @ Nonnull
151- private synchronized Object [] playSound ( Object [] arguments , ILuaContext context , boolean isNote ) throws LuaException
152- {
153- String name = getString (arguments , 0 );
154- float volume = (float ) optReal ( arguments , 1 , 1.0 );
155- float pitch = (float ) optReal ( arguments , 2 , 1.0 );
157+ context .issueMainThreadTask ( () -> {
158+ MinecraftServer server = world .getMinecraftServer ();
159+ if ( server == null ) return null ;
156160
157- ResourceLocation resourceName = new ResourceLocation ( name );
161+ double x = pos .getX () + 0.5 , y = pos .getY () + 0.5 , z = pos .getZ () + 0.5 ;
162+ server .getPlayerList ().sendToAllNearExcept (
163+ null , x , y , z , volume > 1.0f ? 16 * volume : 16.0 , world .provider .getDimension (),
164+ new SPacketCustomSound ( name , SoundCategory .RECORDS , x , y , z , volume , pitch )
165+ );
166+ return null ;
167+ } );
158168
159- if ( m_clock - m_lastPlayTime >= TileSpeaker .MIN_TICKS_BETWEEN_SOUNDS || ( ( m_clock - m_lastPlayTime == 0 ) && ( m_notesThisTick < ComputerCraft .maxNotesPerTick ) && isNote ) )
160- {
161- if ( SoundEvent .REGISTRY .containsKey (resourceName ) )
162- {
163- final World world = getWorld ();
164- final BlockPos pos = getPos ();
165- final ResourceLocation resource = resourceName ;
166- final float vol = volume ;
167- final float soundPitch = pitch ;
168-
169- context .issueMainThreadTask (new ILuaTask ()
170- {
171- @ Nullable
172- @ Override
173- public Object [] execute () throws LuaException
174- {
175- world .playSound ( null , pos , SoundEvent .REGISTRY .getObject ( resource ), SoundCategory .RECORDS , Math .min ( vol , 3f ), soundPitch );
176- return null ;
177- }
178- });
179-
180- m_lastPlayTime = m_clock ;
181- return new Object []{true }; // Success, return true
182- }
183- else
184- {
185- return new Object []{false }; // Failed - sound not existent, return false
186- }
187- }
188- else
189- {
190- return new Object []{false }; // Failed - rate limited, return false
191- }
169+ m_lastPlayTime = m_clock ;
170+ return true ;
192171 }
193172}
194173
0 commit comments