1919
2020package com .sk89q .worldedit .extension .platform ;
2121
22+ import com .google .common .collect .Maps ;
23+ import com .google .common .util .concurrent .ListeningExecutorService ;
24+ import com .google .common .util .concurrent .MoreExecutors ;
2225import com .sk89q .worldedit .LocalConfiguration ;
2326import com .sk89q .worldedit .LocalSession ;
2427import com .sk89q .worldedit .WorldEdit ;
4144import com .sk89q .worldedit .util .HandSide ;
4245import com .sk89q .worldedit .util .Location ;
4346import com .sk89q .worldedit .util .SideEffect ;
47+ import com .sk89q .worldedit .util .concurrency .EvenMoreExecutors ;
4448import com .sk89q .worldedit .util .eventbus .Subscribe ;
49+ import com .sk89q .worldedit .util .lifecycle .SimpleLifecycled ;
4550import com .sk89q .worldedit .world .World ;
4651import org .apache .logging .log4j .Logger ;
4752
@@ -69,7 +74,8 @@ public class PlatformManager {
6974
7075 private final WorldEdit worldEdit ;
7176 private final PlatformCommandManager platformCommandManager ;
72- private final List <Platform > platforms = new ArrayList <>();
77+ private final SimpleLifecycled <ListeningExecutorService > executorService ;
78+ private final Map <Platform , Boolean > platforms = Maps .newHashMap ();
7379 private final Map <Capability , Platform > preferences = new EnumMap <>(Capability .class );
7480 private @ Nullable String firstSeenVersion ;
7581 private final AtomicBoolean initialized = new AtomicBoolean ();
@@ -84,6 +90,7 @@ public PlatformManager(WorldEdit worldEdit) {
8490 checkNotNull (worldEdit );
8591 this .worldEdit = worldEdit ;
8692 this .platformCommandManager = new PlatformCommandManager (worldEdit , this );
93+ this .executorService = SimpleLifecycled .invalid ();
8794
8895 // Register this instance for events
8996 worldEdit .getEventBus ().register (this );
@@ -101,7 +108,7 @@ public synchronized void register(Platform platform) {
101108
102109 // Just add the platform to the list of platforms: we'll pick favorites
103110 // once all the platforms have been loaded
104- platforms .add (platform );
111+ platforms .put (platform , false );
105112
106113 // Make sure that versions are in sync
107114 if (firstSeenVersion != null ) {
@@ -126,7 +133,7 @@ public synchronized void register(Platform platform) {
126133 public synchronized boolean unregister (Platform platform ) {
127134 checkNotNull (platform );
128135
129- boolean removed = platforms .remove (platform );
136+ boolean removed = platforms .remove (platform ) != null ;
130137
131138 if (removed ) {
132139 LOGGER .info ("Unregistering " + platform .getClass ().getCanonicalName () + " from WorldEdit" );
@@ -212,7 +219,7 @@ private synchronized void choosePreferred() {
212219 Platform preferred = null ;
213220 Preference highest = null ;
214221
215- for (Platform platform : platforms ) {
222+ for (Platform platform : platforms . keySet () ) {
216223 Preference preference = platform .getCapabilities ().get (capability );
217224 if (preference != null && (highest == null || preference .isPreferredOver (highest ))) {
218225 preferred = platform ;
@@ -231,7 +238,7 @@ private synchronized void choosePreferred() {
231238 * @return a list of platforms
232239 */
233240 public synchronized List <Platform > getPlatforms () {
234- return new ArrayList <>(platforms );
241+ return new ArrayList <>(platforms . keySet () );
235242 }
236243
237244 /**
@@ -284,6 +291,21 @@ public PlatformCommandManager getPlatformCommandManager() {
284291 return platformCommandManager ;
285292 }
286293
294+ /**
295+ * Get the executor service. Internal, not for API use.
296+ *
297+ * @return the executor service
298+ */
299+ public ListeningExecutorService getExecutorService () {
300+ return executorService .valueOrThrow ();
301+ }
302+
303+ private static ListeningExecutorService createExecutor () {
304+ return MoreExecutors .listeningDecorator (
305+ EvenMoreExecutors .newBoundedCachedThreadPool (
306+ 0 , 1 , 20 , "WorldEdit Task Executor - %s" ));
307+ }
308+
287309 /**
288310 * Get the current configuration.
289311 *
@@ -340,6 +362,10 @@ public void handlePlatformsRegistered(PlatformsRegisteredEvent event) {
340362 @ Subscribe
341363 public void handleNewPlatformReady (PlatformReadyEvent event ) {
342364 preferences .forEach ((cap , platform ) -> cap .ready (this , platform ));
365+ platforms .put (event .getPlatform (), true );
366+ if (!executorService .isValid ()) {
367+ executorService .newValue (createExecutor ());
368+ }
343369 }
344370
345371 /**
@@ -348,6 +374,11 @@ public void handleNewPlatformReady(PlatformReadyEvent event) {
348374 @ Subscribe
349375 public void handleNewPlatformUnready (PlatformUnreadyEvent event ) {
350376 preferences .forEach ((cap , platform ) -> cap .unready (this , platform ));
377+ platforms .put (event .getPlatform (), false );
378+ if (!platforms .containsValue (true )) {
379+ executorService .value ().ifPresent (ListeningExecutorService ::shutdownNow );
380+ executorService .invalidate ();
381+ }
351382 }
352383
353384 @ Subscribe
0 commit comments