44import java .util .Collections ;
55import java .util .HashMap ;
66import java .util .List ;
7- import java .util .concurrent .Callable ;
7+ import java .util .Map ;
8+ import java .util .concurrent .locks .Lock ;
9+ import java .util .concurrent .locks .ReentrantLock ;
810
911import org .bukkit .Bukkit ;
1012import org .bukkit .entity .Player ;
@@ -14,8 +16,7 @@ public abstract class SongPlayer {
1416 protected Song song ;
1517 protected boolean playing = false ;
1618 protected short tick = -1 ;
17- //protected ArrayList<String> playerList = new ArrayList<String>();
18- protected HashMap <String , Boolean > playerList = new HashMap <String , Boolean >();
19+ protected Map <String , Boolean > playerList = Collections .synchronizedMap (new HashMap <String , Boolean >());
1920 protected boolean autoDestroy = false ;
2021 protected boolean destroyed = false ;
2122 protected Thread playerThread ;
@@ -25,10 +26,13 @@ public abstract class SongPlayer {
2526 protected int fadeDuration = 60 ;
2627 protected int fadeDone = 0 ;
2728 protected FadeType fadeType = FadeType .FADE_LINEAR ;
28-
29+ private final Lock lock = new ReentrantLock ();
30+ protected NoteBlockPlayerMain plugin ;
31+
2932 public SongPlayer (Song song ) {
3033 this .song = song ;
31- createThread ();
34+ plugin = NoteBlockPlayerMain .plugin ;
35+ start ();
3236 }
3337
3438 public FadeType getFadeType () {
@@ -80,94 +84,63 @@ protected void calculateFade() {
8084 fadeDone ++;
8185 }
8286
83- protected void createThread () {
84- playerThread = new Thread (new Runnable () {
85- @ Override
86- public void run () {
87- while (!destroyed ) {
88- long startTime = System .currentTimeMillis ();
89- /*synchronized (SongPlayer.this) {
90- if (playing) {
91- calculateFade();
92- tick++;
93- if (tick > song.getLength()) {
94- playing = false;
95- tick = -1;
96- SongEndEvent event = new SongEndEvent(SongPlayer.this);
97- Bukkit.getPluginManager().callEvent(event);
98- if (autoDestroy) {
99- destroy();
100- return;
101- }
102- }
103- for (String s : playerList) {
104- @SuppressWarnings("deprecation")
105- Player p = Bukkit.getPlayerExact(s);
106- if (p == null) {
107- // offline...
108- continue;
109- }
110- playTick(p, tick);
111- }
112- }
113- }*/
114-
115- try {
116- synchronized (Bukkit .getScheduler ()) {
117- if (destroyed || NoteBlockPlayerMain .plugin .disabling ){
118- break ;
119- }
120- Bukkit .getScheduler ().callSyncMethod (NoteBlockPlayerMain .plugin , new Callable <Boolean >() {
121- public Boolean call () {
122- if (playing ) {
123- calculateFade ();
124- tick ++;
125- if (tick > song .getLength ()) {
126- playing = false ;
127- tick = -1 ;
128- SongEndEvent event = new SongEndEvent (SongPlayer .this );
129- Bukkit .getPluginManager ().callEvent (event );
130- if (autoDestroy ) {
131- destroy ();
132- return false ;
133- }
134- }
135- for (String s : playerList .keySet ()) {
136- @ SuppressWarnings ("deprecation" )
137- Player p = Bukkit .getPlayerExact (s );
138- if (p == null ) {
139- // offline...
140- continue ;
141- }
142- playTick (p , tick );
143- }
144- }
145- return true ;
146- }
147- });
148- }
149- } catch (java .lang .IllegalStateException e ) {
150- e .printStackTrace ();
151- }
152-
153- if (destroyed ){
87+ @ SuppressWarnings ("deprecation" )
88+ private void start () {
89+ plugin .doAsync (() -> {
90+ while (!destroyed ) {
91+ long startTime = System .currentTimeMillis ();
92+ lock .lock ();
93+ try {
94+ if (destroyed || NoteBlockPlayerMain .plugin .isDisabling ()){
15495 break ;
15596 }
156-
157- long duration = System .currentTimeMillis () - startTime ;
158- float delayMillis = song .getDelay () * 50 ;
159- if (duration < delayMillis ) {
160- try {
161- Thread .sleep ((long ) (delayMillis - duration ));
162- } catch (InterruptedException e ) {
163- // do nothing
97+
98+ if (playing ) {
99+ calculateFade ();
100+ tick ++;
101+ if (tick > song .getLength ()) {
102+ playing = false ;
103+ tick = -1 ;
104+ SongEndEvent event = new SongEndEvent (SongPlayer .this );
105+ plugin .doSync (() -> Bukkit .getPluginManager ().callEvent (event ));
106+ if (autoDestroy ) {
107+ destroy ();
108+ }
109+ return ;
164110 }
111+
112+ plugin .doSync (() -> {
113+ for (String s : playerList .keySet ()) {
114+ Player p = Bukkit .getPlayerExact (s );
115+ if (p == null ) {
116+ // offline...
117+ continue ;
118+ }
119+ playTick (p , tick );
120+ }
121+ });
122+ }
123+ } catch (Exception e ) {
124+ e .printStackTrace ();
125+ } finally {
126+ lock .unlock ();
127+ }
128+
129+ if (destroyed ){
130+ break ;
131+ }
132+
133+ long duration = System .currentTimeMillis () - startTime ;
134+ float delayMillis = song .getDelay () * 50 ;
135+ if (duration < delayMillis ) {
136+ try {
137+ Thread .sleep ((long ) (delayMillis - duration ));
138+ } catch (InterruptedException e ) {
139+ // do nothing
165140 }
166141 }
167142 }
168143 });
169- playerThread .setPriority (Thread .MAX_PRIORITY );
170- playerThread .start ();
171144 }
172145
173146 public List <String > getPlayerList () {
@@ -177,7 +150,8 @@ public List<String> getPlayerList() {
177150 }
178151
179152 public void addPlayer (Player p ) {
180- synchronized (this ) {
153+ lock .lock ();
154+ try {
181155 if (!playerList .containsKey (p .getName ())) {
182156 playerList .put (p .getName (), false );
183157 ArrayList <SongPlayer > songs = NoteBlockPlayerMain .plugin .playingSongs
@@ -188,27 +162,36 @@ public void addPlayer(Player p) {
188162 songs .add (this );
189163 NoteBlockPlayerMain .plugin .playingSongs .put (p .getName (), songs );
190164 }
191- }
165+ } finally {
166+ lock .unlock ();
167+ }
192168 }
193169
194170
195171
196172 public boolean getAutoDestroy () {
197- synchronized (this ) {
173+ lock .lock ();
174+ try {
198175 return autoDestroy ;
199- }
176+ } finally {
177+ lock .unlock ();
178+ }
200179 }
201180
202181 public void setAutoDestroy (boolean value ) {
203- synchronized (this ) {
182+ lock .lock ();
183+ try {
204184 autoDestroy = value ;
205- }
185+ } finally {
186+ lock .unlock ();
187+ }
206188 }
207189
208190 public abstract void playTick (Player p , int tick );
209191
210192 public void destroy () {
211- synchronized (this ) {
193+ lock .lock ();
194+ try {
212195 SongDestroyingEvent event = new SongDestroyingEvent (this );
213196 Bukkit .getPluginManager ().callEvent (event );
214197 //Bukkit.getScheduler().cancelTask(threadId);
@@ -218,7 +201,9 @@ public void destroy() {
218201 destroyed = true ;
219202 playing = false ;
220203 setTick ((short ) -1 );
221- }
204+ } finally {
205+ lock .unlock ();
206+ }
222207 }
223208
224209 public boolean isPlaying () {
@@ -238,11 +223,12 @@ public short getTick() {
238223 }
239224
240225 public void setTick (short tick ) {
241- this .tick = tick ;
226+ this .tick = tick ;
242227 }
243228
244229 public void removePlayer (Player p ) {
245- synchronized (this ) {
230+ lock .lock ();
231+ try {
246232 playerList .remove (p .getName ());
247233 if (NoteBlockPlayerMain .plugin .playingSongs .get (p .getName ()) == null ) {
248234 return ;
@@ -256,7 +242,9 @@ public void removePlayer(Player p) {
256242 Bukkit .getPluginManager ().callEvent (event );
257243 destroy ();
258244 }
259- }
245+ } finally {
246+ lock .unlock ();
247+ }
260248 }
261249
262250 public byte getVolume () {
0 commit comments