### Example Startup Script Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md Launch the Folia server with specified JVM arguments and memory allocation. ```bash #!/bin/bash java -Xmx4G -Xms4G \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -XX:ConcGCThreads=2 \ -jar folia.jar nogui ``` -------------------------------- ### Example Server Properties Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md Configure basic server settings like player count and view distance. ```properties max-players=100 view-distance=10 simulation-distance=10 network-compression-threshold=256 use-native-transport=true ``` -------------------------------- ### Example Global Paper Configuration Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md Set up threaded regions and chunk loading distances for performance. ```yaml threaded-regions: threads: 8 chunk-loading: view-distance: 10 simulation-distance: 10 spark: enabled: false ``` -------------------------------- ### Plugin Compatibility Documentation Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/DOCUMENTATION_SUMMARY.txt Guides and information on ensuring plugin compatibility with Folia. ```markdown Plugin compatibility documentation created ``` -------------------------------- ### Scheduling a Task Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Provides examples of how to schedule tasks for execution on different schedulers. ```APIDOC ## Scheduling a Task ### Description Schedule tasks to run on specific threads or scopes, including region, entity, global, and asynchronous execution. ### Code Examples ```java // Schedule to a specific region (based on location) Bukkit.getRegionScheduler().schedule(plugin, task -> { /* runs on the region thread */ }, () -> { /* retired callback, often null */ }, location, 0L // delay in ticks ); // Schedule to an entity's associated region entity.getScheduler().schedule(plugin, task -> { /* runs on the entity's region thread */ }, () -> { /* retired callback, often null */ }, 0L // delay in ticks ); // Schedule to the global region thread Bukkit.getGlobalRegionScheduler().run(plugin, task -> { /* runs on the global thread */ } ); // Schedule a task to run asynchronously on a thread pool Bukkit.getAsyncScheduler().runNow(plugin, task -> { /* runs on a separate thread pool */ } ); ``` ``` -------------------------------- ### Schedule Periodic Backups Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/04-async-scheduler.md Utilize `runAtFixedRate` to schedule recurring tasks, such as world backups. This example runs every 10 minutes. Ensure proper error handling for I/O operations. ```java public void setupBackupSchedule() { Bukkit.getAsyncScheduler().runAtFixedRate( plugin, task -> { System.out.println("Starting backup..."); try { backupWorldToFile(); System.out.println("Backup complete"); } catch (IOException e) { e.printStackTrace(); } }, 0L, // Start immediately 12000L // Every 10 minutes ); } ``` -------------------------------- ### Setup Scheduled Region Monitoring Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/07-region-tps-api.md Sets up a repeating task to check TPS for all players' regions every 20 seconds. Logs a warning if any region's 5-second average TPS drops below 18.0. Requires a plugin instance to schedule the task. ```java public void setupRegionMonitoring() { Bukkit.getGlobalRegionScheduler().runAtFixedRate( plugin, task -> { Bukkit.getOnlinePlayers().forEach(player -> { double[] tps = Bukkit.getRegionTPS(player.getLocation()); if (tps != null && tps[0] < 18.0) { // Log warning for debugging Bukkit.getLogger().warning( "Low TPS at " + player.getName() + ": " + String.format("%.2f", tps[0]) ); } }); }, 0L, 400L // Every 20 seconds ); } ``` -------------------------------- ### Get Plugin Description Information Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/08-plugin-compatibility.md Retrieve details such as the author and version from a plugin's description file. ```java Plugin plugin = Bukkit.getPluginManager().getPlugin("MyPlugin"); PluginDescriptionFile desc = plugin.getDescription(); String author = desc.getAuthors().get(0); String version = desc.getVersion(); ``` -------------------------------- ### Coordinate Global Events Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Schedules a task to initialize global state and notify all players when a global event starts. This ensures all players receive the notification simultaneously. ```java public void startGlobalEvent() { Bukkit.getGlobalRegionScheduler().run(plugin, task -> { // Initialize global state eventStartTime = System.currentTimeMillis(); // Notify all players Bukkit.getOnlinePlayers().forEach(p -> { p.sendMessage("Global event started!"); }); }); } ``` -------------------------------- ### Set Java Heap Size for Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md Allocate sufficient heap memory for Folia, recommending at least 2GB more than a Paper equivalent due to region threading. Example sets 8GB. ```bash # Recommended: at least 2GB more than Paper equivalent java -Xmx8G -Xms8G -jar folia.jar nogui ``` -------------------------------- ### Accessing Bukkit World and Region TPS Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Demonstrates how to get a standard Bukkit World and its region TPS. All standard Bukkit World methods are available in Folia. ```java World world = Bukkit.getWorld("world"); double[] tps = Bukkit.getRegionTPS(world, 0, 0); ``` -------------------------------- ### Handling Scheduler Exceptions in Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Provides an example of how to catch potential exceptions, such as NullPointerException or general Exceptions, when scheduling tasks using Bukkit's RegionScheduler. ```java try { Bukkit.getRegionScheduler().schedule( plugin, task -> {}, () -> {}, location, 0L ); } catch (NullPointerException e) { System.out.println("Invalid parameter: " + e.getMessage()); } catch (Exception e) { System.out.println("Scheduling failed: " + e); } ``` -------------------------------- ### Scheduling Tasks in Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/README.md Examples of scheduling tasks to run on specific region threads, the global region thread, or asynchronously. Use these to ensure operations are performed in the correct thread context. ```java entity.getScheduler().schedule(plugin, task -> entity.damage(5), () -> {}, 0L); ``` ```java Bukkit.getRegionScheduler().schedule(plugin, task -> block.setType(Material.STONE), () -> {}, location, 0L); ``` ```java Bukkit.getGlobalRegionScheduler().run(plugin, task -> Bukkit.broadcast(msg)); ``` ```java Bukkit.getAsyncScheduler().runNow(plugin, task -> database.save()); ``` -------------------------------- ### Schedule World-Wide Announcements Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Schedules a task to send announcements to players via the action bar at a specified tick interval. The task starts immediately. ```java public void scheduleTickingAnnouncement(String message, int tickInterval) { Bukkit.getGlobalRegionScheduler().runAtFixedRate( plugin, task -> { Bukkit.getOnlinePlayers().forEach(p -> { p.sendActionBar(Component.text(message)); }); }, 0L, tickInterval ); } ``` -------------------------------- ### Async Web API Call with Global Region Broadcast Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/04-async-scheduler.md Perform an asynchronous HTTP GET request using `runNow`. Upon receiving the response, schedule a task on the global region scheduler to broadcast the deserialized JSON message. This handles external API interactions safely. ```java public void fetchAndBroadcast(String apiUrl) { Bukkit.getAsyncScheduler().runNow(plugin, task -> { try { String jsonResponse = httpGet(apiUrl); // Schedule broadcast back to global region Bukkit.getGlobalRegionScheduler().run( plugin, schedTask -> { Component message = deserializeJson(jsonResponse); Bukkit.broadcast(message); } ); } catch (IOException e) { e.printStackTrace(); } }); } ``` -------------------------------- ### Accessing Schedulers Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Demonstrates how to obtain different scheduler instances for various scheduling needs. ```APIDOC ## Accessing Schedulers ### Description Obtain scheduler instances for different scopes: region-based, entity-based, global region, and asynchronous operations. ### Code Examples ```java // Location-based scheduler RegionScheduler regionScheduler = Bukkit.getRegionScheduler(); // Entity-based scheduler (on an entity object) EntityScheduler entityScheduler = entity.getScheduler(); // Global region scheduler GlobalRegionScheduler globalScheduler = Bukkit.getGlobalRegionScheduler(); // Asynchronous/Background scheduler AsyncScheduler asyncScheduler = Bukkit.getAsyncScheduler(); ``` ``` -------------------------------- ### Accessing Schedulers Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Demonstrates how to obtain different scheduler instances for region-based, entity-based, global, and asynchronous tasks. ```java // Location-based RegionScheduler regionScheduler = Bukkit.getRegionScheduler(); // Entity-based (on entity) EntityScheduler entityScheduler = entity.getScheduler(); // Global region GlobalRegionScheduler globalScheduler = Bukkit.getGlobalRegionScheduler(); // Async/Background AsyncScheduler asyncScheduler = Bukkit.getAsyncScheduler(); ``` -------------------------------- ### Get Chunk Coordinates and Region TPS Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Define chunk coordinates and retrieve the TPS for that specific chunk. ```java int chunkX = 5; int chunkZ = 10; Chunk chunk = world.getChunkAt(chunkX, chunkZ); double[] tps = Bukkit.getRegionTPS(world, chunkX, chunkZ); ``` -------------------------------- ### Get Region TPS Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/README.md Retrieve the current TPS (ticks per second) for a specific region. The result is an array where the first element is the 5-second average. ```java double[] tps = Bukkit.getRegionTPS(location); if (tps != null) { System.out.println("Region TPS: " + tps[0]); // 5-second average } ``` -------------------------------- ### Iterate Over Online Players and Get Region TPS Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Iterate through all players currently online and retrieve their region's TPS (ticks per second). ```java for (Player player : Bukkit.getOnlinePlayers()) { double[] tps = Bukkit.getRegionTPS(player.getLocation()); // Process player } ``` -------------------------------- ### Configuration Documentation Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/DOCUMENTATION_SUMMARY.txt Comprehensive documentation for Folia's configuration options. ```markdown Configuration documentation created ``` -------------------------------- ### Quick Reference Cheat Sheet Creation Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/DOCUMENTATION_SUMMARY.txt Generation of a quick reference cheat sheet for common queries. ```markdown Quick reference cheat sheet created ``` -------------------------------- ### Get Global TPS in Paper/Spigot Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/07-region-tps-api.md Retrieves the single global TPS value for the entire server in Paper/Spigot. This is the traditional method for monitoring server performance. ```java double[] globalTps = Bukkit.getTPS(); // Single value for whole server ``` -------------------------------- ### README Master Index Creation Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/DOCUMENTATION_SUMMARY.txt Creation of a master index file for the README. ```markdown README master index created ``` -------------------------------- ### API Reference Pages Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/DOCUMENTATION_SUMMARY.txt Documentation includes API reference pages for 6 schedulers and other key APIs. ```markdown API reference pages created (6 schedulers/APIs) ``` -------------------------------- ### Async Data Load and Region Apply Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/04-async-scheduler.md Load player data asynchronously using `runNow` and then schedule the application of that data back to the player's specific region using `player.getScheduler().schedule`. This ensures player data modifications happen on the correct thread. ```java public void loadPlayerDataAsync(Player player) { Bukkit.getAsyncScheduler().runNow(plugin, task -> { // Load from database asynchronously PlayerData data = database.loadPlayer(player.getUniqueId()); // Schedule back to player's region to apply data player.getScheduler().schedule( plugin, regionTask -> { // Now safely modify player on region thread player.setHealth(data.health); player.setFoodLevel(data.hunger); player.setExp(data.experience); }, () -> {}, // Optional completion callback 0L // Delay in ticks ); }); } ``` -------------------------------- ### Thread Context API Documentation Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/DOCUMENTATION_SUMMARY.txt Detailed documentation for the Thread Context API, including safety patterns. ```markdown Thread context API documented ``` -------------------------------- ### Check Entity Ownership for Thread Safety Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/README.md Before accessing an entity, check if it is owned by the current region to ensure thread safety. This example shows a safe damage operation. ```java // Check before accessing if (Bukkit.isOwnedByCurrentRegion(entity)) { entity.damage(5); // Safe } ``` -------------------------------- ### Accessing Plugin Description File Metadata Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Demonstrates how to retrieve metadata from a plugin's description file, including Folia support status, name, and version. ```java PluginDescriptionFile desc = plugin.getDescription(); boolean supported = desc.isFoliaSupported(); String name = desc.getName(); String version = desc.getVersion(); ``` -------------------------------- ### Get Chunk Entities with Thread Check Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/06-thread-context-api.md Verifies that the current thread owns the region of a given chunk before accessing its entities. Throws an `IllegalStateException` if the thread context is incorrect. ```java public void getChunkEntities(Chunk chunk) { if (!Bukkit.isOwnedByCurrentRegion(chunk)) { throw new IllegalStateException("Wrong thread for chunk: " + chunk); } return chunk.getEntities(); } ``` -------------------------------- ### Get Region TPS in Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/07-region-tps-api.md Retrieves per-region TPS values in Folia, allowing identification of specific lagging regions. This is useful for pinpointing performance bottlenecks within the server. ```java double[] regionTps = Bukkit.getRegionTPS(location); // Per-region TPS ``` -------------------------------- ### Folia Server Architecture Overview Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Illustrates the multi-threaded region-based architecture of the Folia server, highlighting independent ticking regions and a global main thread for coordination. ```text Folia Server │ ├── Region 1 (Thread 1) │ ├── Chunk Grid (32x32) │ ├── Entities │ ├── TileEntities │ └── Tick Loop │ ├── Region 2 (Thread 2) │ ├── Chunk Grid (32x32) │ ├── Entities │ ├── TileEntities │ └── Tick Loop │ ├── Region N (Thread N) │ └── ... │ └── Global Region (Main Thread) ├── Console commands ├── Server announcements └── Cross-region coordination ``` -------------------------------- ### Scheduling Tasks Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Shows how to schedule tasks to run on region threads, entity-specific regions, global regions, or asynchronously. ```java // To region (location) Bukkit.getRegionScheduler().schedule(plugin, task -> { /* runs on region thread */ }, () -> { /* retired callback */ }, location, 0L // delay ticks ); // To entity entity.getScheduler().schedule(plugin, task -> { /* runs on entity's region */ }, () -> { /* retired callback */ }, 0L // delay ticks ); // To global region Bukkit.getGlobalRegionScheduler().run(plugin, task -> { /* runs on global thread */ } ); // Asynchronously Bukkit.getAsyncScheduler().runNow(plugin, task -> { /* runs on thread pool */ } ); ``` -------------------------------- ### Asynchronous Database Load with Region Callback Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/11-migration-guide.md Shows how to perform blocking database operations asynchronously using `Bukkit.getAsyncScheduler().runNow()` and then schedule the result callback to the player's specific region thread for safe UI updates. ```java @EventHandler public void onJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); // Async load Bukkit.getAsyncScheduler().runNow(plugin, task -> { PlayerData data = database.loadPlayer(player.getUniqueId()); // Schedule callback to player's region player.getScheduler().schedule(plugin, regionTask -> applyPlayerData(player, data), () -> {}, 0L ); }); } ``` -------------------------------- ### Pre-generate World with Paper Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md This bash command initiates world pre-generation using Paper's tools. It is recommended to run this in Folia's pre-generation mode if available to reduce chunk system contention and improve region behavior. ```bash # Use Paper's world pre-generation # (Run in Folia's pre-generation mode if available) ``` -------------------------------- ### Iterate Over Supported Plugins Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Loop through all loaded plugins and check if they support Folia. ```java for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { if (plugin.getDescription().isFoliaSupported()) { // Process plugin } } ``` -------------------------------- ### Schedule Safe Entity State Modification Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/03-entity-scheduler.md Schedules a task to safely modify a mob's attributes on its region thread, preventing potential concurrency issues. This example sets the mob to be non-aggressive. ```java public void makeMobFriendly(LivingEntity mob) { mob.getScheduler().schedule( plugin, task -> { // Safe to modify mob attributes on its region thread mob.setTarget(null); mob.setAggressiveTarget(null); mob.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE) .setBaseValue(0); }, () -> {}, // No completion action 0L ); } ``` -------------------------------- ### Plugin Data Race Condition Example Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/11-migration-guide.md Demonstrates a common race condition in plugins where shared data is accessed from multiple threads without proper synchronization. This can occur with Folia's region-specific threads. ```java public class MyPlugin { private List data = new ArrayList<>(); // Not thread-safe! @EventHandler public void onEvent(SomeEvent event) { data.add("value"); // Race condition from region threads } } ``` -------------------------------- ### Monitor Region Health Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/07-region-tps-api.md Checks the 5-second average TPS for a given location and prints a status message (CRITICAL, WARNING, OK). Use this to get a quick overview of a specific region's performance. ```java public void monitorRegionHealth(Location location) { double[] tps = Bukkit.getRegionTPS(location); if (tps == null) { System.out.println("No region at location"); return; } double currentTps = tps[0]; // 5-second average if (currentTps < 10.0) { System.out.println("CRITICAL: Region below 50% TPS"); } else if (currentTps < 15.0) { System.out.println("WARNING: Region lagging"); } else { System.out.println("OK: Region healthy"); } } ``` -------------------------------- ### Database Query with Async Scheduler and Callback Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/12-quick-reference.md Performs a database query asynchronously and then schedules a callback on the player's region scheduler upon completion. Avoids blocking the main thread. ```java Bukkit.getAsyncScheduler().runNow(plugin, t -> { Data d = db.load(); player.getScheduler().schedule(plugin, rt -> doStuff(d), () -> {}, 0L); }); ``` -------------------------------- ### Get Region TPS Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md This Java code snippet demonstrates how to retrieve and print the current TPS (ticks per second) for a specific region using the Bukkit API. This is useful for monitoring region performance. ```java double[] tps = Bukkit.getRegionTPS(location); System.out.println("Region TPS: " + tps[0]); ``` -------------------------------- ### Monitoring Region Performance (TPS) Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Demonstrates how to retrieve the current 5-second and 1-minute TPS for a specific region using its location or chunk coordinates. ```java // Get TPS for region at location double[] tps = Bukkit.getRegionTPS(location); if (tps != null) { double current5sTps = tps[0]; double current1mTps = tps[2]; } // Get TPS for region at chunk double[] tps = Bukkit.getRegionTPS(chunk); // Get TPS for region at coordinates double[] tps = Bukkit.getRegionTPS(world, chunkX, chunkZ); ``` -------------------------------- ### run Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Runs a task immediately on the next global tick. The task is executed on the global region thread. ```APIDOC ## run ### Description Runs a task immediately on the next global tick. The task is executed on the global region thread. ### Method `run` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Parameters - **plugin** (Plugin) - Required - The plugin scheduling the task - **task** (Consumer) - Required - The task to execute ### Return Type `ScheduledTask` ### Thread Context Called from any thread; execution on global tick thread ### Example ```java Bukkit.getGlobalRegionScheduler().run(plugin, task -> { // Executes on global region thread Bukkit.broadcastMessage("Server announcement!"); }); ``` ``` -------------------------------- ### Get Region TPS by Chunk Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/07-region-tps-api.md Retrieves the TPS data for the region that owns a given chunk. This method is useful for checking the performance of a specific chunk's region. The TPS data includes averages over different time intervals. ```java Chunk chunk = world.getChunkAt(0, 0); double[] tps = Bukkit.getRegionTPS(chunk); if (tps != null && tps[0] < 15.0) { System.out.println("Chunk's region is lagging!"); } ``` -------------------------------- ### Get Region TPS by Location Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/07-region-tps-api.md Retrieves the TPS data for the region containing a specific location. The returned array contains 5-second, 15-second, 1-minute, 5-minute, and 15-minute average TPS values. Returns null if the location is not owned by any region. ```java Location playerLocation = player.getLocation(); double[] tps = Bukkit.getRegionTPS(playerLocation); if (tps != null) { System.out.println("5s TPS: " + tps[0]); System.out.println("15s TPS: " + tps[1]); System.out.println("1m TPS: " + tps[2]); System.out.println("5m TPS: " + tps[3]); System.out.println("15m TPS: " + tps[4]); } else { System.out.println("Location has no owning region"); } ``` -------------------------------- ### Check Folia Compatibility using PluginDescriptionFile Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/08-plugin-compatibility.md Instantiate `PluginDescriptionFile` with a `plugin.yml` stream and use its `isFoliaSupported()` method to check compatibility. ```java PluginDescriptionFile description = new PluginDescriptionFile( new java.io.InputStreamReader( getResource("plugin.yml") ) ); if (description.isFoliaSupported()) { System.out.println("Plugin is Folia-compatible"); } ``` -------------------------------- ### Player Move Event Handler - Incorrect Threading Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/11-migration-guide.md This example shows an incorrect implementation of a player move event handler where entity operations might occur on the wrong thread. Avoid direct entity manipulation without thread safety checks. ```java @EventHandler public void onPlayerMove(PlayerMoveEvent event) { Player player = event.getPlayer(); Entity nearby = getNearbyEntity(); // WRONG - entity may be on different region nearby.damage(5); } ``` -------------------------------- ### Configure Java Garbage Collection for Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md Tune GC settings for optimal region threading performance. Key parameters include MaxGCPauseMillis and ConcGCThreads, which should be tuned based on core count. ```bash java -Xmx8G -Xms8G \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -XX:+ParallelRefProcEnabled \ -XX:ConcGCThreads=4 # Tune based on core count \ -jar folia.jar nogui ``` -------------------------------- ### Get Region TPS by Chunk Coordinates Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/07-region-tps-api.md Retrieves TPS data for a region based on world and chunk coordinates. This allows for checking region performance without needing a direct Chunk object. The output format is an array of time-averaged TPS values. ```java World world = Bukkit.getWorld("world"); double[] tps = Bukkit.getRegionTPS(world, 0, 0); if (tps != null) { System.out.printf("Region at (0,0): %.2f TPS (5s avg)%n", tps[0]); } ``` -------------------------------- ### Optimize World Generator Settings Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md Configure world generation settings in paper-global.yml. Setting `use-vanilla: true` is recommended for pre-generating worlds to reduce chunk system worker thread load. ```yaml world-settings: default: chunk-generator: # Tune generator if using custom generators use-vanilla: true ``` -------------------------------- ### Schedule Task with Task Handle Access Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/12-quick-reference.md This snippet demonstrates how to schedule a task and receive a handle to it. The handle allows checking if the task is cancelled or cancelling it directly, which is particularly useful for repeating tasks. ```java scheduler.schedule(plugin, task -> { // task parameter allows checking/cancelling: if (task.isCancelled()) { return; } task.cancel(); // Cancel repeating tasks }, () -> {}, location, 0L ); ``` -------------------------------- ### Server Properties Configuration Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Defines essential server properties including view distance, simulation distance, and maximum player count. ```properties view-distance=10 simulation-distance=10 max-players=100 ``` -------------------------------- ### Retrieve Region TPS Array Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/12-quick-reference.md Get the TPS (ticks per second) for a specific region using Bukkit.getRegionTPS(...). The returned double array contains averages for 5 seconds, 15 seconds, 1 minute, 5 minutes, and 15 minutes. Handle null return values if no region exists at the specified location. ```java double[] tps = Bukkit.getRegionTPS(...); if (tps != null) { tps[0] // 5-second average TPS tps[1] // 15-second average TPS tps[2] // 1-minute average TPS tps[3] // 5-minute average TPS tps[4] // 15-minute average TPS } else { // No region at that location } ``` -------------------------------- ### Performance Monitoring Documentation Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/DOCUMENTATION_SUMMARY.txt Documentation covering performance monitoring tools and implications. ```markdown Performance monitoring documented ``` -------------------------------- ### Monitoring Performance Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Shows how to retrieve performance metrics, specifically TPS (Ticks Per Second), for different regions. ```APIDOC ## Monitoring Performance ### Description Retrieve performance data, such as TPS, for specific regions identified by location, chunk, or coordinates. ### Code Examples ```java // Get TPS for the region containing a specific location double[] tps = Bukkit.getRegionTPS(location); if (tps != null) { double current5sTps = tps[0]; // 5-second TPS double current1mTps = tps[2]; // 1-minute TPS } // Get TPS for the region containing a specific chunk double[] tps = Bukkit.getRegionTPS(chunk); // Get TPS for the region at specific world coordinates double[] tps = Bukkit.getRegionTPS(world, chunkX, chunkZ); ``` ``` -------------------------------- ### Check Plugin Compatibility at Runtime Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/08-plugin-compatibility.md Iterates through all loaded plugins to check if they are marked as Folia-supported. Logs a warning for incompatible plugins. ```java public void checkPluginCompatibility() { for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { if (!plugin.getDescription().isFoliaSupported()) { Bukkit.getLogger().warning( "Plugin '" + plugin.getName() + "' is not Folia-compatible" ); } } } ``` -------------------------------- ### runNow Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/04-async-scheduler.md Runs a task immediately on an async thread. This method is suitable for tasks that need to be executed without any delay. ```APIDOC ## runNow ### Description Runs a task immediately on an async thread. ### Method `ScheduledTask runNow(Plugin plugin, Consumer task)` ### Parameters #### Path Parameters - **plugin** (Plugin) - Required - The plugin scheduling the task - **task** (Consumer) - Required - The task to execute ### Request Example ```java Bukkit.getAsyncScheduler().runNow(plugin, task -> { // Running asynchronously, NOT on region thread try { String result = fetchDataFromDatabase(); System.out.println("Got: " + result); } catch (Exception e) { e.printStackTrace(); } }); ``` ### Response #### Success Response - **ScheduledTask** - The scheduled task object ``` -------------------------------- ### Correctly Teleporting Entities Asynchronously in Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/08-plugin-compatibility.md Demonstrates the correct way to teleport entities in Folia using the asynchronous teleport method. ```java entity.teleportAsync(destination).thenAccept(success -> { if (success) { System.out.println("Teleported"); } }); ``` -------------------------------- ### Scheduling Tasks with Bukkit RegionScheduler Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Illustrates scheduling a task using the Bukkit RegionScheduler, which is available for plugins in Folia. Requires a Plugin instance. ```java Plugin plugin = this; // in JavaPlugin Bukkit.getRegionScheduler().schedule(plugin, task -> {}, () -> {}, location, 0L); ``` -------------------------------- ### Schedule Fixed-Rate Task on LivingEntity Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Schedule a task to run at a fixed rate on a LivingEntity using its scheduler. ```java LivingEntity mob = (LivingEntity) entity; mob.getScheduler().scheduleAtFixedRate( plugin, task -> {}, () -> {}, 0L, 1L ); ``` -------------------------------- ### In-Game TPS Command Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md Check current tick performance using the /bukkit:tps command. ```text /bukkit:tps # Shows current tick performance # Additional Folia-specific monitoring available through plugins ``` -------------------------------- ### Correctly Using Region-Aware Schedulers in Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/08-plugin-compatibility.md Shows the correct method for scheduling tasks in Folia using region-aware schedulers to avoid errors. ```java player.getScheduler().schedule(plugin, task -> player.setHealth(10), () -> {}, 0L ); ``` -------------------------------- ### Schedule Global Task Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/README.md Use this for global operations like broadcasting messages or running console commands. Requires a plugin instance and a task lambda. ```java Bukkit.getGlobalRegionScheduler().run(plugin, task -> {...}); ``` -------------------------------- ### Scheduling Back to Region Thread Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/04-async-scheduler.md Demonstrates the correct way to apply asynchronous results back to the game world by scheduling a task on the player's region scheduler. Direct modification of world data from an async task will cause a crash. ```java Bukkit.getAsyncScheduler().runNow(plugin, task -> { String result = doAsyncWork(); // WRONG - will crash: // player.setHealth(10); // RIGHT - schedule back to region: player.getScheduler().schedule( plugin, regionTask -> { player.setHealth(10); }, () -> {}, 0L ); }); ``` -------------------------------- ### Async Database Load with Callback in Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/00-index.md Load player data asynchronously from a database and then update the player's stats on the main thread using the player's scheduler. This ensures thread-safe UI updates. ```java public void loadPlayerData(Player player) { Bukkit.getAsyncScheduler().runNow(plugin, task -> { PlayerData data = database.load(player.getUniqueId()); player.getScheduler().schedule(plugin, regionTask -> { player.setHealth(data.health); player.setFoodLevel(data.hunger); }, () -> {}, 0L ); }); } ``` -------------------------------- ### Thread-Safe List for Plugin Data Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/11-migration-guide.md Shows how to use `Collections.synchronizedList` to create a thread-safe list for plugin data, preventing race conditions when accessed from multiple threads. ```java private List data = Collections.synchronizedList( new ArrayList<>() ); ``` -------------------------------- ### Verify Folia Support at Plugin Startup Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/08-plugin-compatibility.md Ensure your plugin is marked as Folia-compatible during its `onEnable` method. If not compatible, it will be logged and disabled. ```java public class MyPlugin extends JavaPlugin { @Override public void onEnable() { // Verify Folia marking if (!getDescription().isFoliaSupported()) { Bukkit.getLogger().severe( "This plugin is not marked as Folia-compatible!" ); Bukkit.getPluginManager().disablePlugin(this); return; } Bukkit.getLogger().info("MyPlugin enabled on Folia"); } } ``` -------------------------------- ### Scheduler Delay Constraints Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Demonstrates the non-negative constraint for scheduler delay parameters. Negative delays will result in an error, while zero or positive delays are accepted. ```java scheduler.schedule(plugin, t -> {}, () -> {}, location, -1L); // Error! scheduler.schedule(plugin, t -> {}, () -> {}, location, 0L); // OK scheduler.schedule(plugin, t -> {}, () -> {}, location, 100L); // OK ``` -------------------------------- ### Schedule Async Task Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/README.md Use this for asynchronous operations such as I/O, database access, or networking. Requires a plugin instance and a task lambda. ```java Bukkit.getAsyncScheduler().runNow(plugin, task -> {...}); ``` -------------------------------- ### Location-Based Operation - Solution using Region Scheduler Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/11-migration-guide.md This solution demonstrates the correct way to perform location-based operations, such as modifying blocks, by using Bukkit's RegionScheduler. This ensures the operation is executed on the appropriate thread for the given location. ```java public void modifyBlock(Location loc) { Bukkit.getRegionScheduler().schedule(plugin, task -> { loc.getBlock().setType(Material.STONE); }, () -> {}, loc, 0L // execute next tick ); } ``` -------------------------------- ### Scheduling to Global Region for Thread Safety Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/11-migration-guide.md Demonstrates how to use `Bukkit.getGlobalRegionScheduler().run()` to execute code on the global thread, ensuring thread safety for operations that modify shared data structures. ```java private List data = new ArrayList<>(); @EventHandler public void onEvent(SomeEvent event) { Bukkit.getGlobalRegionScheduler().run(plugin, task -> { data.add("value"); // Safe on global thread }); } ``` -------------------------------- ### Schedule Server Maintenance Tasks Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Sets up a recurring task to perform server maintenance, such as cleaning up offline player data and flushing caches. Runs every 5 minutes after an initial 1-minute delay. ```java public void setupMaintenanceTasks() { Bukkit.getGlobalRegionScheduler().runAtFixedRate( plugin, task -> { // Cleanup disconnected players cleanupOfflinePlayerData(); // Flush caches flushCachedData(); }, 1200L, // 1 minute 6000L // Every 5 minutes ); } ``` -------------------------------- ### Execute Console Commands Globally Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Schedules a task to execute a console command on the global thread. This is useful for commands that need to be run with server privileges. ```java public void executeConsoleCommand(String command) { Bukkit.getGlobalRegionScheduler().run(plugin, task -> { // Execute console command on global thread Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); }); } ``` -------------------------------- ### Create and Schedule Task at Location Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Instantiate a Folia Location object and schedule a task to run at that specific location. ```java Location loc = new Location(world, 100.5, 64, 100.5); Bukkit.getRegionScheduler().schedule( plugin, task -> {}, () -> {}, loc, 0L ); ``` -------------------------------- ### Safe Handling of ScheduledTask Scheduling Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Demonstrates how to safely schedule a task and handle potential exceptions, ensuring the task object is non-null before use. This pattern is useful for preventing null pointer exceptions when interacting with the scheduler. ```java try { ScheduledTask task = Bukkit.getRegionScheduler().schedule( plugin, t -> {}, () -> {}, location, 0L ); // task is guaranteed non-null here if (!task.isCancelled()) { task.cancel(); } } catch (Exception e) { System.out.println("Scheduling failed: " + e); } ``` -------------------------------- ### Schedule Task on Player Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Schedule a task to be executed for a player, including sending a message. ```java Player player = ...; player.getScheduler().schedule( plugin, task -> player.sendMessage("Message"), () -> {}, 0L ); ``` -------------------------------- ### Run Server-Wide Broadcasts Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Schedules a task to broadcast a message to all players on the server. This is safe to perform from the global thread. ```java public void broadcastAnnouncement(String message) { Bukkit.getGlobalRegionScheduler().run(plugin, task -> { // Safe to broadcast to all players from global thread Component component = Component.text(message) .color(NamedTextColor.YELLOW); Bukkit.broadcast(component); }); } ``` -------------------------------- ### Migrate BukkitScheduler to GlobalRegionScheduler Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Compares the old Paper API for scheduling repeating tasks with the new Folia API for global region scheduling. Use this snippet to update existing repeating task implementations. ```java // Old Paper code: Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, () -> { doGlobalWork(); }, 0L, 100L); // New Folia code: Bukkit.getGlobalRegionScheduler().runAtFixedRate(plugin, task -> { doGlobalWork(); }, 0L, 100L); ``` -------------------------------- ### runAtFixedRate Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Schedules a repeating task on the global region thread with an initial delay and a fixed period. ```APIDOC ## runAtFixedRate ### Description Schedules a repeating task on the global region thread with an initial delay and a fixed period. ### Method `runAtFixedRate` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Parameters - **plugin** (Plugin) - Required - The plugin scheduling the task - **task** (Consumer) - Required - The task to repeat - **initialDelayTicks** (long) - Required - Ticks before first execution - **periodTicks** (long) - Required - Ticks between executions ### Return Type `ScheduledTask` ### Example ```java Bukkit.getGlobalRegionScheduler().runAtFixedRate( plugin, task -> { // Check online players every 20 ticks int count = Bukkit.getOnlinePlayers().size(); System.out.println("Players online: " + count); }, 0L, // Start immediately 20L // Every second ); ``` ``` -------------------------------- ### Run Repeating Task on Global Region Thread Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/05-global-region-scheduler.md Schedules a task to repeat at a fixed rate on the global region thread. Allows for periodic global operations with a specified initial delay and interval. ```java Bukkit.getGlobalRegionScheduler().runAtFixedRate( plugin, task -> { // Check online players every 20 ticks int count = Bukkit.getOnlinePlayers().size(); System.out.println("Players online: " + count); }, 0L, // Start immediately 20L // Every second ); ``` -------------------------------- ### Incorrect World Loading in Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/08-plugin-compatibility.md Illustrates the incorrect method of loading a world directly in Folia, as world loading is not fully implemented. ```java // WRONG - world loading not fully implemented World world = Bukkit.createWorld(new WorldCreator("world2")); ``` -------------------------------- ### Scheduler Period Constraints Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/10-types.md Illustrates the non-zero constraint for scheduler repeat periods. A period of zero is an error, while a period of one or greater is valid. ```java scheduler.scheduleAtFixedRate( plugin, t -> {}, () -> {}, location, 0L, 0L // Error! ); scheduler.scheduleAtFixedRate( plugin, t -> {}, () -> {}, location, 0L, 1L // OK ); ``` -------------------------------- ### Run Database Save Asynchronously Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/04-async-scheduler.md Use `runNow` on the async scheduler to perform blocking database operations without freezing the main thread. The task is executed immediately. ```java public void savePlayerData(UUID playerId, PlayerData data) { Bukkit.getAsyncScheduler().runNow(plugin, task -> { database.savePlayer(playerId, data); System.out.println("Saved player: " + playerId); }); } ``` -------------------------------- ### Configure Watchdog Thread Settings Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/09-configuration.md Set the watchdog's check interval and the maximum allowed time for a region tick. If a region exceeds max-tick-time, it will be forcefully interrupted. ```yaml paper-global.yml: watchdog: period: 10 # Check interval in seconds max-tick-time: 60 # Max time for region tick (seconds) ``` -------------------------------- ### Optimize Database Queries with Folia Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/11-migration-guide.md Compares inefficient database querying methods (every tick) with a more optimized approach (every 20 ticks) and the best practice of using events for data retrieval in Folia. ```java // Bad: Query database every tick entity.getScheduler().scheduleAtFixedRate(plugin, task -> { data = database.query(); // Every tick! }, () -> {}, 0L, 1L); // Good: Query less frequently entity.getScheduler().scheduleAtFixedRate(plugin, task -> { data = database.query(); // Every 20 ticks }, () -> {}, 0L, 20L); // Better: Use events @EventHandler public void onEvent(RelevantEvent event) { data = database.query(); // Only when needed } ``` -------------------------------- ### Essential Imports for Folia Schedulers Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/12-quick-reference.md These imports are necessary to utilize Folia's scheduler APIs and related Bukkit functionalities. ```java import io.papermc.paper.threadedregions.scheduler.*; import org.bukkit.Bukkit; import org.bukkit.entity.Entity; import org.bukkit.Location; ``` -------------------------------- ### Run Async Task Immediately Source: https://github.com/papermc/folia/blob/ver/26.1.x/_autodocs/04-async-scheduler.md Schedules a task to run immediately on an asynchronous thread. Use for I/O operations or heavy computations that do not require region thread access. ```java Bukkit.getAsyncScheduler().runNow(plugin, task -> { // Running asynchronously, NOT on region thread try { String result = fetchDataFromDatabase(); System.out.println("Got: " + result); } catch (Exception e) { e.printStackTrace(); } }); ```