pop4959 / Chunky

Pre-generates chunks, quickly, efficiently, and safely.
GNU General Public License v3.0
570 stars 64 forks source link

Have Chunky detect if players are online and auto pause/continue #29

Closed Strahilchu closed 2 years ago

Strahilchu commented 4 years ago

I'm requesting a feature that pauses Chunky when a player is online and continues it only when the server is empty. Perhaps like a check every half hour or configurable time to check for players, would be great for small community servers that have periods of time with no players such as during the night.

Ideally a check every 20 minutes(or a listener, I don't know whats more efficient) to see if players are online if yes, pause chunky, if already paused, do nothing. If server is empty, run /chunky continue

pop4959 commented 4 years ago

Sounds good to me. Thanks for posting here on Github so I can track this better.

By the way, we can probably do this much more efficiently (check when a player joins / quits and immediately update the status). No need for some sort of timer thing, as that's just wasted time that could be spent generating chunks!

Strahilchu commented 4 years ago

Thanks for looking into and considering my feature suggestion! It would be so convenient to have this, I would set it to generate worlds and overtime it will complete without anyone noticing. :)

Yey007 commented 3 years ago

Hey! Is this being worked on by someone at the moment? If not I may try it. I've done a little bit of work to play around (using the event listeners to start/stop tasks when players join/leave), but there is still some work to do, like making a config option and getting chunky start, chunky continue, etc. to work properly with the option enabled.

pop4959 commented 3 years ago

Hey! Is this being worked on by someone at the moment? If not I may try it. I've done a little bit of work to play around (using the event listeners to start/stop tasks when players join/leave), but there is still some work to do, like making a config option and getting chunky start, chunky continue, etc. to work properly with the option enabled.

I'm not currently working on it, so you're welcome to do some testing if you'd like to try to figure something out. My initial thoughts on implementation here was to poll for resources (such as player count) synchronously and then check these values in the generation task.

Note: I've been working on refactoring portions of the code base, so just keep that in mind. I will probably not be merging anything else until I'm finished with that. Please message me on Discord if you want to know more about that.

emielderckx commented 3 years ago

Maybe add a config to choose number of players online. (A lot of times one player is afking and then chunky can run perfectly

Yey007 commented 3 years ago

This will be added in #58 (if it gets merged) @emielderckx

Jipok commented 2 years ago

I made a simple datapack that checks if the server is empty every 5 seconds. Continues/pauses generation accordingly.

Screenshot with code ![image](https://user-images.githubusercontent.com/25588359/142902342-06fb829d-207a-4871-a43b-1f060776ebc6.png)

Although it runs the command every 5 seconds even if it's already running, it doesn't seem to have any performance impact. Continue/pause commands were moved to separate functions as they didn't work through execute .... run chunky <cmd>

alexanderhorner commented 2 years ago

Is this still being worked on? Seems like a simple thing to do but very important feature in my opinion

pop4959 commented 2 years ago

@alexanderhorner Good question, here are my thoughts currently as I have not posted an update on this issue in a while:

I've been a bit hesitant to go forward with this feature as it encourages pre-generating with players online which kind of defeats the purpose of doing so in the first place for the majority of servers, since the reason you're doing it is to give players a better chunk loading experience, which is not going to be the case if you pre-gen while or after players have already joined.

In addition, pre-generation generally does not lag the server at all on modern versions of Minecraft, even with players online. Chunk loading will be somewhat throttled, but any lag or TPS drops are usually not directly related.

I have not yet closed this issue as I may still add options to control the rate, but for the most part it seems superficial and there have not been many requests for it, so it's been lower priority for me. I encourage you to try for yourself and give anecdotal evidence if you're not convinced, but there have even been raspberry pi's running without issues, and that's about as low-end as it gets in terms of running Minecraft servers.

Zeklandia commented 2 years ago

I am also interested in this feature. For us, being able to leave Chunky running while players are on the server would let us avoid taking the server down for half a day or more instead. We use Chunky infrequently, usually around game updates. Since upgrading to 1.18, we have been using it to upgrade the old terrain, both to make it easier on players exploring and also to let Dynmap render it (terrain that hasn't been upgraded to 1.18 can't be rendered by Dynmap).

When we do run Chunky, it is virtually impossible to load new chunks. As long as players stay within the chunks they already have loaded, they can continue to play as normal. If Chunky were able to scale its work to have the impact of a single player flying around in spectator mode, then we could let it run without worrying about it hindering players, and it would finish its work in about a week. As it stands, we will be running Chunky on and off for probably a month to upgrade the 15k m radius circle in our world. It would take 2–3 days if we closed the server to players, which we don't want to do. Ideally, Chunky should be able to scale its performance impact so that it can take advantage of times when no players are on the server while also letting any players who do connect play the game as normal.

pop4959 commented 2 years ago

Someone also shared a plugin on the Discord server which works similarly to the data pack above. So if you don't like data packs, there's another solution for the time being.

Zeklandia commented 2 years ago

Unfortunately, the plugin is for Spigot (we use Fabric), and I have tried the data pack but it doesn't seem to work (we've had it for two days and it hasn't started Chunky a single time).

pop4959 commented 2 years ago

Unfortunately, the plugin is for Spigot (we use Fabric), and I have tried the data pack but it doesn't seem to work (we've had it for two days and it hasn't started Chunky a single time).

I just tested the data pack and it seems to work for me, at least on Fabric 1.18. I also made some changes in 93b2ffe which should fix compatibility with /execute.

Zeklandia commented 2 years ago

I think the issue with the datapack was that, as downloaded from GitHub, the pack itself wasn't in the root directory of the .zip file. I've repacked it and hopefully now it will work.

pop4959 commented 2 years ago

Yeah I had to unzip it for it to work

alexanderhorner commented 2 years ago

@Jipok's datapack unfortunately gives me the following error:

[17:17:30 INFO]: Found new data pack file/ChunkyPreGen, loading it automatically
[17:17:30 INFO]: Reloading ResourceManager: Default, bukkit, ChunkyPreGen
[17:17:31 INFO]: Loaded 7 recipes
[17:17:31 ERROR]: Failed to load function chunkypregen:pause
java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Whilst parsing command on line 1: Unknown or incomplete command, see below for error at positi
on 0: <--[HERE]
        at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) ~[?:?]
        at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) ~[?:?]
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1770) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
        at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: java.lang.IllegalArgumentException: Whilst parsing command on line 1: Unknown or incomplete command, see below for error at position 0: <--[HERE]
        at net.minecraft.commands.CommandFunction.fromLines(CommandFunction.java:68) ~[?:?]
        at net.minecraft.server.ServerFunctionLibrary.lambda$reload$3(ServerFunctionLibrary.java:86) ~[?:?]
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ~[?:?]
        ... 3 more
[17:17:31 ERROR]: Failed to load function chunkypregen:continue
java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: Whilst parsing command on line 1: Unknown or incomplete command, see below for error at positi
on 0: <--[HERE]
        at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) ~[?:?]
        at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) ~[?:?]
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1770) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
        at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: java.lang.IllegalArgumentException: Whilst parsing command on line 1: Unknown or incomplete command, see below for error at position 0: <--[HERE]
        at net.minecraft.commands.CommandFunction.fromLines(CommandFunction.java:68) ~[?:?]
        at net.minecraft.server.ServerFunctionLibrary.lambda$reload$3(ServerFunctionLibrary.java:86) ~[?:?]
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768) ~[?:?]
        ... 3 more
Zeklandia commented 2 years ago

@alexanderhorner there was an issue with the line endings being mixed between UNIX-style and Windows-style. I fixed this issue by making all the files in the datapack use Windows-style line endings: Chunky Auto v2.zip However, I have found it does not properly stop when players join.

ltjessem commented 2 years ago

I'd like to +1 this issue. Yes, in an ideal world you'd pre-generate everything and nothing would ever change. However, in real life a server can outgrow its current border and need to be expanded, in which case you kind of need to be able to generate chunks while online. Also, it shouldn't lag the server, but again in the real world it does happen.

Dynmap solves this very elegantly with several methods to determine if it should pause itself, and works flawlessly:

# If nonzero, server will pause fullrender/radiusrender processing when 'fullrenderplayerlimit' or more users are logged in
fullrenderplayerlimit: 0
# If nonzero, server will pause update render processing when 'updateplayerlimit' or more users are logged in
updateplayerlimit: 0
# Target limit on server thread use - msec per tick
per-tick-time-limit: 50
# If TPS of server is below this setting, update renders processing is paused
update-min-tps: 18.0
# If TPS of server is below this setting, full/radius renders processing is paused
fullrender-min-tps: 18.0
# If TPS of server is below this setting, zoom out processing is paused
zoomout-min-tps: 18.0
pop4959 commented 2 years ago

With the release of the Developer API, this is now possible via a custom integration.

For example, I have written ChunkyPause for Bukkit servers which allows you to configure a max player count before pausing. The default is 0 which means that the server must be empty for tasks to run.

Of course, you can also control the pausing of tasks by any other criteria if you like. 🎉

ltjessem commented 2 years ago

It's unfortunate that this couldn't be added to Chunky itself, but thank you.

pop4959 commented 2 years ago

It's unfortunate that this couldn't be added to Chunky itself, but thank you.

Let me be clear that by closing this issue I am not ruling out the possibility of adding this to the main plugin in the future, however I just cannot justify it at the moment. Allow me to give more context:

Over the last 2 years since this issue was created, I have spent a lot of time trying to come up with ideas for how to best incorporate this into the plugin without adding too much bloat and encouraging bad practice with pre-generation. I just couldn't think of a way to do that effectively.

The only somewhat sensible pausing method (in my opinion) so far has been player pausing, not for lag but simply to avoid generating chunks when players are also potentially generating chunks, and even that is a bit of a stretch. Most other stuff like pausing for TPS, RAM, and so on would be largely superficial (and has been known to cause problems with older pre-gen plugins like WorldBorder).

That being said, I am providing the API so that server owners and developers can very easily create automations based on their preferences for how they want tasks in chunky to run. I believe this is the right decision in general for "custom functionality", and I am currently looking at doing this with custom shapes as well.

For further discussion into adjacent features let's move into the #chunky channel on the Discord server as I'd like to avoid creating extra email spam for everyone following this resolved issue.

pop4959 commented 5 months ago

Updated version of Jipok's data pack: ChunkyPlayerPause.zip

Used for testing the fix for #334, but uploading here again in case anyone still finds it helpful...