Skip to content

feat(sleep): add autosleep subcommands and manager#1

Merged
QianMo0721 merged 1 commit intoCraftAmethyst:masterfrom
SilkePilon:feat-autosleep-manager-and-commands
Feb 16, 2026
Merged

feat(sleep): add autosleep subcommands and manager#1
QianMo0721 merged 1 commit intoCraftAmethyst:masterfrom
SilkePilon:feat-autosleep-manager-and-commands

Conversation

@SilkePilon
Copy link
Copy Markdown

Add "once", "auto" and "stop" subcommands to the sleep command registration so users can explicitly sleep once, enable automatic sleeping, or disable it. Wire new handlers in SleepCommand:

  • sleepOnce delegates to existing sleep behavior
  • sleepAuto enables autosleep via FakeplayerAutosleepManager
  • sleepStop disables autosleep via the manager Send a generic success message after toggling autosleep.

Introduce FakeplayerAutosleepManager to manage automatic sleeping state for fake players and register it as a listener. Provide methods to check and set autosleep metadata on fake players.

Perform dependency injection for the manager into SleepCommand and add necessary imports and translations. This enables persistent and controlled autosleep behavior for fake players.

Add "once", "auto" and "stop" subcommands to the sleep command
registration so users can explicitly sleep once, enable automatic
sleeping, or disable it. Wire new handlers in SleepCommand:
- sleepOnce delegates to existing sleep behavior
- sleepAuto enables autosleep via FakeplayerAutosleepManager
- sleepStop disables autosleep via the manager
Send a generic success message after toggling autosleep.

Introduce FakeplayerAutosleepManager to manage automatic sleeping
state for fake players and register it as a listener. Provide methods
to check and set autosleep metadata on fake players.

Perform dependency injection for the manager into SleepCommand and
add necessary imports and translations. This enables persistent and
controlled autosleep behavior for fake players.
Copilot AI review requested due to automatic review settings January 26, 2026 21:12
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds automatic sleeping functionality for fake players. Players can now enable automatic sleep mode so their fake players will automatically find and sleep in nearby beds during nighttime.

Changes:

  • Added FakeplayerAutosleepManager to manage automatic sleeping state and schedule periodic checks for nighttime
  • Added three new subcommands to the sleep command: "once" (explicit one-time sleep), "auto" (enable automatic sleeping), and "stop" (disable automatic sleeping)
  • Added AUTOSLEEP metadata key to track which fake players have autosleep enabled

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
FakeplayerAutosleepManager.java New manager class that schedules periodic checks for nighttime and automatically sleeps fake players with autosleep enabled when beds are nearby
MetadataKeys.java Added AUTOSLEEP constant for tracking autosleep state on fake players
SleepCommand.java Added dependency injection for FakeplayerAutosleepManager and three new command methods (sleepOnce, sleepAuto, sleepStop)
CommandRegistry.java Registered three new subcommands (once, auto, stop) under the sleep command with appropriate predicates and handlers
Main.java Registered FakeplayerAutosleepManager as an event listener and started its scheduler during plugin initialization

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +37 to +43
public void setAutosleep(@NotNull Player target, boolean autosleep) {
if (!autosleep) {
target.removeMetadata(MetadataKeys.AUTOSLEEP, Main.getInstance());
} else {
target.setMetadata(MetadataKeys.AUTOSLEEP, new FixedMetadataValue(Main.getInstance(), true));
}
}
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setAutosleep method does not validate whether the target player is actually a fake player. This could lead to setting autosleep metadata on real players if called incorrectly.

Consider adding validation similar to FakeplayerAutofishManager and other managers, or ensure that callers always validate before calling this method. Looking at the codebase pattern in FakeplayerAutofishManager.java:48-61, the validation is typically done at the event handler level, but direct method calls from commands should still be safe.

Copilot uses AI. Check for mistakes.
Comment on lines +413 to +421
.withShortDescription("fakeplayer.command.sleep.once")
.withOptionalArguments(fakeplayer("name", p -> !p.isSleeping()))
.executes(sleepCommand::sleepOnce),
command("auto")
.withShortDescription("fakeplayer.command.sleep.auto")
.withOptionalArguments(fakeplayer("name"))
.executes(sleepCommand::sleepAuto),
command("stop")
.withShortDescription("fakeplayer.command.sleep.stop")
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation keys are missing for the new subcommands. The command registration references "fakeplayer.command.sleep.once", "fakeplayer.command.sleep.auto", and "fakeplayer.command.sleep.stop" but these keys do not exist in any of the translation files (message.properties, message_zh.properties, message_zh_HK.properties, message_zh_TW.properties).

Add the missing translation keys to all translation files to ensure users see proper descriptions for these commands.

Suggested change
.withShortDescription("fakeplayer.command.sleep.once")
.withOptionalArguments(fakeplayer("name", p -> !p.isSleeping()))
.executes(sleepCommand::sleepOnce),
command("auto")
.withShortDescription("fakeplayer.command.sleep.auto")
.withOptionalArguments(fakeplayer("name"))
.executes(sleepCommand::sleepAuto),
command("stop")
.withShortDescription("fakeplayer.command.sleep.stop")
.withShortDescription("fakeplayer.command.sleep.description")
.withOptionalArguments(fakeplayer("name", p -> !p.isSleeping()))
.executes(sleepCommand::sleepOnce),
command("auto")
.withShortDescription("fakeplayer.command.sleep.description")
.withOptionalArguments(fakeplayer("name"))
.executes(sleepCommand::sleepAuto),
command("stop")
.withShortDescription("fakeplayer.command.sleep.description")

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define descriptor key in the message file

Comment on lines +104 to +111
Bukkit.getScheduler().runTaskTimer(Main.getInstance(), () -> {
for (World world : Bukkit.getWorlds()) {
if (world.getEnvironment() != World.Environment.NORMAL) {
continue;
}
checkAndSleep(world);
}
}, 100L, 100L); // Check every 5 seconds (100 ticks)
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scheduled task returned by runTaskTimer should be stored so it can be properly cancelled when the plugin is disabled. This prevents resource leaks and unnecessary background processing after the plugin is disabled.

Consider storing the BukkitTask reference and implementing a cleanup method similar to how other managers in the codebase handle this. For example, you could add a private field to store the task and cancel it in an onDisable method.

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +53
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onTimeSkip(@NotNull TimeSkipEvent event) {
if (event.getSkipReason() != TimeSkipEvent.SkipReason.NIGHT_SKIP) {
return;
}

// When time is skipped due to night, all players slept successfully
// We can use this to know when to re-enable auto sleep for next night
}
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This event handler is registered but contains no implementation logic. The comment suggests it could be used to track when night is skipped, but without implementation, this handler serves no purpose and adds unnecessary overhead.

Either implement the logic to handle the TimeSkipEvent (e.g., to track when players have successfully slept and manage autosleep state), or remove this empty handler if it's not currently needed.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This thing seems to be deletable.
(If you want it to be valuable, it's usually used for controls like "try only once per night/reset after night ends," such as clearing the cooldown or status for the night during NIGHT_SKIP Otherwise, removal is recommended)

@SilkePilon SilkePilon marked this pull request as draft January 26, 2026 21:22
* Schedule a task to check for night time and auto sleep
*/
public void startScheduler() {
Bukkit.getScheduler().runTaskTimer(Main.getInstance(), () -> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The autosleep scheduled task scans the entire world and iterates through all dummies every 5 seconds. It will execute even if no dummies have autosleep enabled, which may cause unnecessary overhead

)
.withOptionalArguments(fakeplayer("name", p -> !p.isSleeping()))
.executes(sleepCommand::sleep),
command("wakeup")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sleep subcommand makes once, auto, and stop reserved words; if a dummy with the same name already exists, sleep will not be executed. The behavior will change (it will be parsed as a subcommand first)

@QianMo0721
Copy link
Copy Markdown
Member

QianMo0721 commented Jan 27, 2026

Thank you, Everything else is fine. Next, implement data persistence or configuration, and then provide a prompt when a bed cannot be found instead of using the silent failure behavior of sleep

@QianMo0721 QianMo0721 self-assigned this Jan 27, 2026
@QianMo0721 QianMo0721 added the enhancement New feature or request label Jan 27, 2026
@QianMo0721 QianMo0721 marked this pull request as ready for review January 27, 2026 16:24
@QianMo0721 QianMo0721 merged commit 181a7cc into CraftAmethyst:master Feb 16, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants