@@ -77,6 +77,8 @@ public class InteractionVisualizer extends JavaPlugin {
7777 public static final int BSTATS_PLUGIN_ID = 7024 ;
7878 public static final String CONFIG_ID = "config" ;
7979 public static final Set <String > SUPPORTED_MINECRAFT_VERSIONS = Set .of ("26.1.2" , "26.2" );
80+ private static final String PERFORMANCE_MIGRATION_MARKER =
81+ ".paper26-performance-defaults-advised" ;
8082
8183 public static InteractionVisualizer plugin = null ;
8284
@@ -114,17 +116,17 @@ public class InteractionVisualizer extends JavaPlugin {
114116
115117 public static boolean defaultDisabledAll = false ;
116118 /** A/B switch: virtual item remains authoritative while an invisible tracker stays stationary. */
117- public static boolean staticVirtualItemAnchorsDuringAnimation = false ;
119+ public static boolean staticVirtualItemAnchorsDuringAnimation = true ;
118120 /** A/B switch: eligible stationary virtual items are tracked and rendered entirely by packets. */
119- public static boolean packetOnlyStaticVirtualItems = false ;
121+ public static boolean packetOnlyStaticVirtualItems = true ;
120122 /** A/B switch: safe animated virtual items use Typewriter-style per-viewer packet tracking. */
121123 public static boolean packetOnlyAnimatedVirtualItems = false ;
122124 /** A/B switch: smooths visibility recovery bursts; hides are always immediate. */
123- public static boolean visibilityRateLimiting = false ;
125+ public static boolean visibilityRateLimiting = true ;
124126 public static int visibilityRateLimitBucketSize = 128 ;
125127 public static int visibilityRateLimitRestorePerTick = 32 ;
126128 /** A/B switch: coalesces block changes and updates tracked blocks from fixed-budget loops. */
127- public static boolean eventDrivenBlockUpdates = false ;
129+ public static boolean eventDrivenBlockUpdates = true ;
128130 public static int blockUpdateMaxDirtyPerTick = 64 ;
129131
130132 private boolean blockUpdateModeInitialized ;
@@ -181,14 +183,17 @@ public void onEnable() {
181183 if (!getDataFolder ().exists ()) {
182184 getDataFolder ().mkdirs ();
183185 }
186+ File configFile = new File (getDataFolder (), "config.yml" );
187+ boolean existingConfiguration = configFile .isFile ();
184188 try {
185- Config .loadConfig (CONFIG_ID , new File ( getDataFolder (), "config.yml" ) , getClass ().getClassLoader ().getResourceAsStream ("config.yml" ), getClass ().getClassLoader ().getResourceAsStream ("config.yml" ), true );
189+ Config .loadConfig (CONFIG_ID , configFile , getClass ().getClassLoader ().getResourceAsStream ("config.yml" ), getClass ().getClassLoader ().getResourceAsStream ("config.yml" ), true );
186190 } catch (IOException e ) {
187191 e .printStackTrace ();
188192 getServer ().getPluginManager ().disablePlugin (this );
189193 return ;
190194 }
191195 loadConfig ();
196+ advisePerformanceMigrationOnce (existingConfiguration );
192197
193198 boolean craftEngineHooked = CustomContentManager .initialize (this ).contains ("craftengine" );
194199 if (isPluginEnabled ("CraftEngine" )) {
@@ -267,25 +272,41 @@ public void onEnable() {
267272 @ Override
268273 public void onDisable () {
269274 shutdownPerformanceScenes ();
270- if (lightManager != null ) {
271- lightManager .shutdown ();
275+ int retainedLightState = 0 ;
276+ ILightManager disablingLightManager = lightManager ;
277+ if (disablingLightManager != null ) {
278+ disablingLightManager .shutdown ();
279+ retainedLightState = disablingLightManager .retainedStateCount ();
272280 lightManager = ILightManager .DUMMY_INSTANCE ;
273281 }
274- viewerCullingManager .shutdown ();
282+ ViewerCullingManager disablingCullingManager = viewerCullingManager ;
283+ disablingCullingManager .shutdown ();
284+ int retainedCullingRegistrations = disablingCullingManager .retainedRegistrations ();
275285 viewerCullingManager = ViewerCullingManager .DISABLED ;
276286 CustomContentManager .shutdown ();
277- if (preferenceManager != null ) {
278- preferenceManager .close ();
287+ int retainedPreferenceState = 0 ;
288+ PreferenceManager disablingPreferenceManager = preferenceManager ;
289+ if (disablingPreferenceManager != null ) {
290+ disablingPreferenceManager .close ();
291+ retainedPreferenceState = disablingPreferenceManager .retainedStateCount ();
292+ preferenceManager = null ;
279293 }
280294 Database .close ();
281295 TaskManager .shutdown ();
282296 DisplayManager .shutdown ();
283297 TileEntityManager .shutdown ();
284298 PlayerLocationManager .clearCache ();
299+ playerTrackingRange .clear ();
285300 LegacyTextComponentCache .invalidateAll ();
286- if (asyncExecutorManager != null ) {
287- asyncExecutorManager .close ();
301+ int retainedAsyncTasks = 0 ;
302+ AsyncExecutorManager disablingAsyncExecutorManager = asyncExecutorManager ;
303+ if (disablingAsyncExecutorManager != null ) {
304+ disablingAsyncExecutorManager .close ();
305+ retainedAsyncTasks = disablingAsyncExecutorManager .retainedTaskCount ();
306+ asyncExecutorManager = null ;
288307 }
308+ PerformanceMetrics .logShutdownState (this , retainedAsyncTasks ,
309+ retainedPreferenceState , retainedLightState , retainedCullingRegistrations );
289310 getServer ().getConsoleSender ().sendMessage (Component .text (
290311 "[InteractionVisualizer] Disabled; all display entities removed." , NamedTextColor .RED ));
291312 }
@@ -321,6 +342,43 @@ public SparrowConfiguration getConfiguration() {
321342 return Config .getConfig (CONFIG_ID ).getConfiguration ();
322343 }
323344
345+ private void advisePerformanceMigrationOnce (boolean existingConfiguration ) {
346+ File marker = new File (getDataFolder (), PERFORMANCE_MIGRATION_MARKER );
347+ if (marker .isFile ()) {
348+ return ;
349+ }
350+ try {
351+ if (!marker .createNewFile ()) {
352+ return ;
353+ }
354+ } catch (IOException exception ) {
355+ getLogger ().log (Level .WARNING ,
356+ "Unable to persist the Paper 26 performance migration notice marker" , exception );
357+ }
358+ if (existingConfiguration && hasPreservedPerformanceOptOut ()) {
359+ getLogger ().warning ("Paper 26 performance defaults are enabled for new installations. "
360+ + "Your explicit false values were preserved; review StaticAnchorDuringAnimation, "
361+ + "PacketOnlyStatic, VisibilityRateLimit, BlockUpdates.EventDriven, and dropped-item "
362+ + "VisibilityCulling/VisibilityRateLimit when you are ready to migrate." );
363+ }
364+ }
365+
366+ private boolean hasPreservedPerformanceOptOut () {
367+ SparrowConfiguration configuration = getConfiguration ();
368+ return !configuration .getBoolean (
369+ "Settings.Performance.VirtualItems.StaticAnchorDuringAnimation" )
370+ || !configuration .getBoolean (
371+ "Settings.Performance.VirtualItems.PacketOnlyStatic" )
372+ || !configuration .getBoolean (
373+ "Settings.Performance.VisibilityRateLimit.Enabled" )
374+ || !configuration .getBoolean (
375+ "Settings.Performance.BlockUpdates.EventDriven" )
376+ || !configuration .getBoolean (
377+ "Entities.Item.Options.VisibilityCulling.Enabled" )
378+ || !configuration .getBoolean (
379+ "Entities.Item.Options.VisibilityRateLimit.Enabled" );
380+ }
381+
324382 public void loadConfig () {
325383 Config config = Config .getConfig (CONFIG_ID );
326384 config .reload ();
0 commit comments