Bug fixes, config file, more commands
- fixed chunk skips skipping not-generated chunks - changed command structure to /chunkmaster <operation> - added config options - updated readmepull/4/head v0.9-beta
parent
f726f3e15c
commit
52ba24390f
@ -1,17 +1,50 @@
|
|||||||
# chunkmaster
|
# chunkmaster
|
||||||
|
|
||||||
This plugin can be used to pre-generate the region of a world around the spawn chunk. The plugin provides the commands
|
This plugin can be used to pre-generate the region of a world around the spawn chunk.
|
||||||
|
|
||||||
- `/generate [world] [stopAt]` - Pre-generates chunks in the current world until the world border or the stopAt chunk count is reached.
|
|
||||||
- `/listgentasks` - Lists all running generation tasks (and their ids)
|
|
||||||
- `/removegentask [taskId]` - Removes a generation task (stops it permanently)
|
|
||||||
|
|
||||||
The generation automatically pauses when a player joins the server (assuming the server was empty before)
|
The generation automatically pauses when a player joins the server (assuming the server was empty before)
|
||||||
and resumes when the server is empty again. The generation also auto-resumes after a server
|
and resumes when the server is empty again. The generation also auto-resumes after a server
|
||||||
restart. The plugin tracks the ticks per second and pauses the generation when the tps
|
restart. The plugin tracks the ticks per second and pauses the generation when the tps
|
||||||
is lower than 2.
|
is lower than 2.
|
||||||
|
|
||||||
## Future Features
|
## Commands
|
||||||
|
|
||||||
|
All features can be accessed with the command `/chunkmaster` or the aliases `/chm`, `chunkm`, `cmaster`.
|
||||||
|
|
||||||
|
- `/chunkmaster generate [world] [chunk count]` Starts the generation until the specified chunk count or the world border is reached.
|
||||||
|
- `/chunkmaster list` Lists all running generation tasks
|
||||||
|
- `/chunkmaster cancel <Task id>` Cancels the generation task with the specified id (if it is running).
|
||||||
|
- `/chunkmaster pause` Pauses all generation tasks until the resume command is executed.
|
||||||
|
- `/chunkmaster resume` Resumes all paused generation tasks.
|
||||||
|
- `/chunkmaster reload` Reloads the configuration file.
|
||||||
|
|
||||||
|
## Config
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
generation:
|
||||||
|
|
||||||
|
# The period (in ticks) in which a generation step is run.
|
||||||
|
# Higher values mean less performance impact but slower generation.
|
||||||
|
# The value should be a positive integer.
|
||||||
|
period: 2
|
||||||
|
|
||||||
|
# The number of already generated chunks that will be skipped for each step.
|
||||||
|
# Notice that these still have a performance impact because the server needs to check
|
||||||
|
# if the chunk is generated.
|
||||||
|
# Higher values mean faster generation but greater performance impact.
|
||||||
|
# The value should be a positive integer.
|
||||||
|
chunks-skips-per-step: 5
|
||||||
|
|
||||||
|
# The maximum milliseconds per tick the server is allowed to have
|
||||||
|
# during the cunk generation process.
|
||||||
|
# If the mspt is greather than this, the chunk generation task pauses.
|
||||||
|
# The value should be a positive integer greater than 50.
|
||||||
|
mspt-pause-threshold: 500
|
||||||
|
|
||||||
- pause generation tasks until restarted by command
|
# If the chunk generation process should pause on player join.
|
||||||
- configure the tps pause limit
|
# Notice that playing on a server that constantly generates chunks can be
|
||||||
|
# very laggy and can cause it to crash.
|
||||||
|
# You could configure the values above so that the performance impact of the generation
|
||||||
|
# process is minimal.
|
||||||
|
# The value should be a boolean <true/false>
|
||||||
|
pause-on-join: true
|
||||||
|
```
|
@ -0,0 +1,28 @@
|
|||||||
|
package net.trivernis.chunkmaster.commands
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder
|
||||||
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
|
import net.trivernis.chunkmaster.lib.Subcommand
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
class CmdCancel(private val chunkmaster: Chunkmaster): Subcommand {
|
||||||
|
override val name = "cancel"
|
||||||
|
|
||||||
|
override fun execute(sender: CommandSender, args: List<String>): Boolean {
|
||||||
|
return if (args.isNotEmpty() && args[0].toIntOrNull() != null) {
|
||||||
|
if (chunkmaster.generationManager.removeTask(args[0].toInt())) {
|
||||||
|
sender.sendMessage("Task ${args[0]} canceled.")
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
sender.spigot().sendMessage(*ComponentBuilder("Task ${args[0]} not found!")
|
||||||
|
.color(ChatColor.RED).create())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.spigot().sendMessage(*ComponentBuilder("You need to provide a task id to cancel.")
|
||||||
|
.color(ChatColor.RED).create())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package net.trivernis.chunkmaster.commands
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder
|
||||||
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
|
import net.trivernis.chunkmaster.lib.Subcommand
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
|
class CmdGenerate(private val chunkmaster: Chunkmaster): Subcommand {
|
||||||
|
override val name = "generate"
|
||||||
|
|
||||||
|
override fun execute(sender: CommandSender, args: List<String>): Boolean {
|
||||||
|
var worldName = ""
|
||||||
|
var stopAfter = -1
|
||||||
|
if (sender is Player) {
|
||||||
|
if (args.isNotEmpty()) {
|
||||||
|
if (args[0].toIntOrNull() != null) {
|
||||||
|
stopAfter = args[0].toInt()
|
||||||
|
} else {
|
||||||
|
worldName = args[0]
|
||||||
|
}
|
||||||
|
if (args.size > 1 && args[1].toIntOrNull() != null) {
|
||||||
|
stopAfter = args[1].toInt()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
worldName = sender.world.name
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (args.isNotEmpty()) {
|
||||||
|
worldName = args[0]
|
||||||
|
if (args.size > 1 && args[1].toIntOrNull() != null) {
|
||||||
|
stopAfter = args[1].toInt()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.spigot().sendMessage(
|
||||||
|
*ComponentBuilder("You need to provide a world name").color(ChatColor.RED).create())
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val world = chunkmaster.server.getWorld(worldName)
|
||||||
|
return if (world != null) {
|
||||||
|
chunkmaster.generationManager.addTask(world, stopAfter)
|
||||||
|
sender.spigot().sendMessage(*ComponentBuilder("Generation task for world ").color(ChatColor.BLUE)
|
||||||
|
.append(worldName).color(ChatColor.GREEN).append(" until ").color(ChatColor.BLUE)
|
||||||
|
.append(if (stopAfter > 0) "$stopAfter chunks" else "WorldBorder").color(ChatColor.GREEN)
|
||||||
|
.append(" successfully created").color(ChatColor.BLUE).create())
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
sender.spigot().sendMessage(*ComponentBuilder("World ").color(ChatColor.RED)
|
||||||
|
.append(worldName).color(ChatColor.GREEN).append(" not found!").color(ChatColor.RED).create())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package net.trivernis.chunkmaster.commands
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder
|
||||||
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
|
import net.trivernis.chunkmaster.lib.Subcommand
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
class CmdList(private val chunkmaster: Chunkmaster): Subcommand {
|
||||||
|
override val name = "list"
|
||||||
|
|
||||||
|
override fun execute(sender: CommandSender, args: List<String>): Boolean {
|
||||||
|
val runningTasks = chunkmaster.generationManager.tasks
|
||||||
|
if (runningTasks.isEmpty()) {
|
||||||
|
sender.spigot().sendMessage(*ComponentBuilder("There are no running generation tasks.")
|
||||||
|
.color(ChatColor.BLUE).create())
|
||||||
|
} else {
|
||||||
|
val response = ComponentBuilder("Currently running generation tasks:").color(ChatColor.WHITE)
|
||||||
|
for (task in runningTasks) {
|
||||||
|
response.append("\n - #${task.id}: ${task.generationTask.world.name}, Progress ${task.generationTask.count}")
|
||||||
|
.color(ChatColor.BLUE)
|
||||||
|
}
|
||||||
|
sender.spigot().sendMessage(*response.create())
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package net.trivernis.chunkmaster.commands
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder
|
||||||
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
|
import net.trivernis.chunkmaster.lib.Subcommand
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
class CmdPause(private val chunkmaster: Chunkmaster) : Subcommand {
|
||||||
|
override val name: String = "pause"
|
||||||
|
|
||||||
|
override fun execute(sender: CommandSender, args: List<String>): Boolean {
|
||||||
|
return if (!chunkmaster.generationManager.paused) {
|
||||||
|
chunkmaster.generationManager.pauseAll()
|
||||||
|
sender.spigot().sendMessage(
|
||||||
|
*ComponentBuilder("Paused all generation tasks.")
|
||||||
|
.color(ChatColor.BLUE).create()
|
||||||
|
)
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
sender.spigot().sendMessage(
|
||||||
|
*ComponentBuilder("The generation process is already paused.").color(ChatColor.RED).create()
|
||||||
|
)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package net.trivernis.chunkmaster.commands
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder
|
||||||
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
|
import net.trivernis.chunkmaster.lib.Subcommand
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
class CmdResume(private val chunkmaster: Chunkmaster): Subcommand {
|
||||||
|
override val name = "resume"
|
||||||
|
|
||||||
|
override fun execute(sender: CommandSender, args: List<String>): Boolean {
|
||||||
|
return if (chunkmaster.generationManager.paused) {
|
||||||
|
chunkmaster.generationManager.resumeAll()
|
||||||
|
sender.spigot().sendMessage(
|
||||||
|
*ComponentBuilder("Resumed all generation tasks.").color(ChatColor.BLUE).create())
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
sender.spigot().sendMessage(
|
||||||
|
*ComponentBuilder("There are no paused generation tasks.").color(ChatColor.RED).create())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package net.trivernis.chunkmaster.commands
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.ChatColor
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder
|
||||||
|
import net.trivernis.chunkmaster.Chunkmaster
|
||||||
|
import net.trivernis.chunkmaster.lib.Subcommand
|
||||||
|
import org.bukkit.Server
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.CommandExecutor
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
import org.bukkit.command.TabCompleter
|
||||||
|
|
||||||
|
class CommandChunkmaster(private val chunkmaster: Chunkmaster, private val server: Server): CommandExecutor,
|
||||||
|
TabCompleter {
|
||||||
|
private val commands = HashMap<String, Subcommand>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
registerCommands()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tab complete for commands
|
||||||
|
*/
|
||||||
|
override fun onTabComplete(sender: CommandSender, command: Command, alias: String, args: Array<out String>):
|
||||||
|
MutableList<String> {
|
||||||
|
return commands.keys.filter { it.indexOf(args[0]) == 0 }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /chunkmaster command to handle all commands
|
||||||
|
*/
|
||||||
|
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
||||||
|
if (args.isNotEmpty()) {
|
||||||
|
when (args[0]) {
|
||||||
|
"reload" -> {
|
||||||
|
chunkmaster.reloadConfig()
|
||||||
|
sender.sendMessage("Configuration file reloaded.")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
if (sender.hasPermission("chunkmaster.${args[0]}")) {
|
||||||
|
return if (commands.containsKey(args[0])) {
|
||||||
|
commands[args[0]]!!.execute(sender, args.slice(1 until args.size))
|
||||||
|
} else {
|
||||||
|
sender.spigot().sendMessage(*ComponentBuilder("Subcommand ").color(ChatColor.RED)
|
||||||
|
.append(args[0]).color(ChatColor.GREEN).append(" not found").color(ChatColor.RED).create())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sender.spigot().sendMessage(*ComponentBuilder("You do not have permission!")
|
||||||
|
.color(ChatColor.RED).create())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerCommands() {
|
||||||
|
val cmdGenerate = CmdGenerate(chunkmaster)
|
||||||
|
commands[cmdGenerate.name] = cmdGenerate
|
||||||
|
|
||||||
|
val cmdPause = CmdPause(chunkmaster)
|
||||||
|
commands[cmdPause.name] = cmdPause
|
||||||
|
|
||||||
|
val cmdResume = CmdResume(chunkmaster)
|
||||||
|
commands[cmdResume.name] = cmdResume
|
||||||
|
|
||||||
|
val cmdCancel = CmdCancel(chunkmaster)
|
||||||
|
commands[cmdCancel.name] = cmdCancel
|
||||||
|
|
||||||
|
val cmdList = CmdList(chunkmaster)
|
||||||
|
commands[cmdList.name] = cmdList
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.commands
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.Chunkmaster
|
|
||||||
import org.bukkit.command.Command
|
|
||||||
import org.bukkit.command.CommandExecutor
|
|
||||||
import org.bukkit.command.CommandSender
|
|
||||||
import org.bukkit.entity.Player
|
|
||||||
|
|
||||||
class CommandGenerate(private val chunkmaster: Chunkmaster): CommandExecutor {
|
|
||||||
/**
|
|
||||||
* Start world generation task on commmand
|
|
||||||
*/
|
|
||||||
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
|
||||||
if (sender is Player) {
|
|
||||||
return if (command.testPermission(sender)) {
|
|
||||||
var stopAfter = -1
|
|
||||||
|
|
||||||
if (args.isNotEmpty() && args[0].toIntOrNull() != null) {
|
|
||||||
stopAfter = args[0].toInt()
|
|
||||||
}
|
|
||||||
chunkmaster.generationManager.addTask(sender.world, stopAfter)
|
|
||||||
sender.sendMessage("Added generation task for world \"${sender.world.name}\"" +
|
|
||||||
"Stopping after $stopAfter chunks (-1 for world border).")
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
sender.sendMessage("You do not have permission.")
|
|
||||||
true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return if (args.size >= 1) {
|
|
||||||
val world = sender.server.getWorld(args[0])
|
|
||||||
if (world != null) {
|
|
||||||
var stopAfter = -1
|
|
||||||
|
|
||||||
if (args.size >=2 && args[1].toIntOrNull() != null) {
|
|
||||||
stopAfter = args[1].toInt()
|
|
||||||
}
|
|
||||||
chunkmaster.generationManager.addTask(world, stopAfter)
|
|
||||||
|
|
||||||
sender.sendMessage("Added generation task for world \"${world.name}\"" +
|
|
||||||
"Stopping after $stopAfter chunks (-1 for world border).")
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
sender.sendMessage("World \"${args[0]}\" not found")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sender.sendMessage("You need to specify a world")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.commands
|
|
||||||
|
|
||||||
import net.md_5.bungee.api.ChatColor
|
|
||||||
import net.md_5.bungee.api.chat.ComponentBuilder
|
|
||||||
import net.trivernis.chunkmaster.Chunkmaster
|
|
||||||
import org.bukkit.command.Command
|
|
||||||
import org.bukkit.command.CommandExecutor
|
|
||||||
import org.bukkit.command.CommandSender
|
|
||||||
|
|
||||||
class CommandListGenTasks(private val chunkmaster: Chunkmaster): CommandExecutor {
|
|
||||||
/**
|
|
||||||
* Responds with a list of running generation tasks.
|
|
||||||
*/
|
|
||||||
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
|
||||||
val runningTasks = chunkmaster.generationManager.tasks
|
|
||||||
val response = ComponentBuilder("Currently running generation tasks").color(ChatColor.BLUE)
|
|
||||||
for (task in runningTasks) {
|
|
||||||
response.append("\n - #${task.id}: ${task.generationTask.world.name}, Progress ${task.generationTask.count}")
|
|
||||||
}
|
|
||||||
response.color(ChatColor.GREEN)
|
|
||||||
sender.spigot().sendMessage(*response.create())
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package net.trivernis.chunkmaster.commands
|
|
||||||
|
|
||||||
import net.trivernis.chunkmaster.Chunkmaster
|
|
||||||
import org.bukkit.command.Command
|
|
||||||
import org.bukkit.command.CommandExecutor
|
|
||||||
import org.bukkit.command.CommandSender
|
|
||||||
|
|
||||||
class CommandRemoveGenTask(private val chunkmaster: Chunkmaster): CommandExecutor {
|
|
||||||
/**
|
|
||||||
* Stops the specified generation task and removes it from the autostart.
|
|
||||||
*/
|
|
||||||
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
|
||||||
return if (command.testPermission(sender) && args.size == 1) {
|
|
||||||
chunkmaster.generationManager.removeTask(args[0].toInt())
|
|
||||||
sender.sendMessage("Task ${args[1].toInt()} canceled.")
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
sender.sendMessage("Invalid argument.")
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,8 @@
|
|||||||
|
package net.trivernis.chunkmaster.lib
|
||||||
|
|
||||||
|
import org.bukkit.command.CommandSender
|
||||||
|
|
||||||
|
interface Subcommand {
|
||||||
|
val name: String
|
||||||
|
fun execute(sender: CommandSender, args: List<String>): Boolean
|
||||||
|
}
|
Loading…
Reference in New Issue