Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ public class ENTimeAndWeatherMessages extends OkaeriConfig implements TimeAndWea
Notice weatherSetSun = Notice.chat("<color:#9d6eef>► <white>Weather set to sun in the <color:#9d6eef>{WORLD}<white>!");
Notice weatherSetThunder =
Notice.chat("<color:#9d6eef>► <white>Weather set to thunder in the <color:#9d6eef>{WORLD}<white>!");
Notice weatherPersistenceEnabled =
Notice.chat("<color:#9d6eef>► <white>Locked <color:#9d6eef>{WEATHER}<white> weather in the <color:#9d6eef>{WORLD}<white> world.");
Notice weatherPersistenceDisabled =
Notice.chat("<color:#9d6eef>► <white>Natural weather cycle enabled again in the <color:#9d6eef>{WORLD}<white> world.");
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ public class PLTimeAndWeatherMessages extends OkaeriConfig implements TimeAndWea
Notice weatherSetSun =
Notice.chat("<color:#9d6eef>► <white>Ustawiono słoneczną pogodę w świecie <color:#9d6eef>{WORLD}<white>!");
Notice weatherSetThunder = Notice.chat("<color:#9d6eef>► <white>Ustawiono burze w świecie <color:#9d6eef>{WORLD}<white>!");
Notice weatherPersistenceEnabled =
Notice.chat("<color:#9d6eef>► <white>Zablokowano pogodę <color:#9d6eef>{WEATHER}<white> w świecie <color:#9d6eef>{WORLD}<white>.");
Notice weatherPersistenceDisabled =
Notice.chat("<color:#9d6eef>► <white>Przywrócono naturalny cykl pogody w świecie <color:#9d6eef>{WORLD}<white>!");
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ public interface TimeAndWeatherMessages {
Notice weatherSetRain();
Notice weatherSetSun();
Notice weatherSetThunder();
Notice weatherPersistenceEnabled();
Notice weatherPersistenceDisabled();
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.eternalcode.core.feature.weather;

import com.eternalcode.annotations.scan.command.DescriptionDocs;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.notice.NoticeService;
import com.eternalcode.core.viewer.Viewer;
Expand All @@ -18,12 +17,12 @@
class RainCommand {

private final NoticeService noticeService;
private final MinecraftScheduler scheduler;
private final WeatherService weatherService;

@Inject
RainCommand(NoticeService noticeService, MinecraftScheduler scheduler) {
RainCommand(NoticeService noticeService, WeatherService weatherService) {
this.noticeService = noticeService;
this.scheduler = scheduler;
this.weatherService = weatherService;
}

@Execute
Expand All @@ -39,10 +38,7 @@ void rainWorld(@Sender Viewer viewer, @Arg World world) {
}

private void setRain(Viewer viewer, World world) {
this.scheduler.run(() -> {
world.setStorm(true);
world.setThundering(false);
});
this.weatherService.setWeather(world, WeatherType.RAIN, false);

this.noticeService.create()
.viewer(viewer)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.eternalcode.core.feature.weather;

import com.eternalcode.annotations.scan.command.DescriptionDocs;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.notice.NoticeService;
import com.eternalcode.core.viewer.Viewer;
Expand All @@ -18,12 +17,12 @@
class SunCommand {

private final NoticeService noticeService;
private final MinecraftScheduler scheduler;
private final WeatherService weatherService;

@Inject
SunCommand(NoticeService noticeService, MinecraftScheduler scheduler) {
SunCommand(NoticeService noticeService, WeatherService weatherService) {
this.noticeService = noticeService;
this.scheduler = scheduler;
this.weatherService = weatherService;
}

@Execute
Expand All @@ -39,11 +38,7 @@ void sunWorld(@Sender Viewer viewer, @Arg World world) {
}

private void setSun(Viewer viewer, World world) {
this.scheduler.run(() -> {
world.setClearWeatherDuration(20 * 60 * 10);
world.setStorm(false);
world.setThundering(false);
});
this.weatherService.setWeather(world, WeatherType.SUN, false);

this.noticeService.create()
.viewer(viewer)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.eternalcode.core.feature.weather;

import com.eternalcode.annotations.scan.command.DescriptionDocs;
import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.notice.NoticeService;
import com.eternalcode.core.viewer.Viewer;
Expand All @@ -18,12 +17,12 @@
class ThunderCommand {

private final NoticeService noticeService;
private final MinecraftScheduler scheduler;
private final WeatherService weatherService;

@Inject
ThunderCommand(NoticeService noticeService, MinecraftScheduler scheduler) {
ThunderCommand(NoticeService noticeService, WeatherService weatherService) {
this.noticeService = noticeService;
this.scheduler = scheduler;
this.weatherService = weatherService;
}

@Execute
Expand All @@ -39,10 +38,7 @@ void thunderWorld(@Sender Viewer viewer, @Arg World world) {
}

private void setThunder(Viewer viewer, World world) {
this.scheduler.run(() -> {
world.setStorm(true);
world.setThundering(true);
});
this.weatherService.setWeather(world, WeatherType.THUNDER, false);

this.noticeService.create()
.viewer(viewer)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.eternalcode.core.feature.weather;

import com.eternalcode.annotations.scan.command.DescriptionDocs;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.notice.NoticeService;
import com.eternalcode.core.viewer.Viewer;
import dev.rollczi.litecommands.annotations.argument.Arg;
import dev.rollczi.litecommands.annotations.command.Command;
import dev.rollczi.litecommands.annotations.context.Context;
import dev.rollczi.litecommands.annotations.context.Sender;
import dev.rollczi.litecommands.annotations.execute.Execute;
import dev.rollczi.litecommands.annotations.flag.Flag;
import dev.rollczi.litecommands.annotations.permission.Permission;
import java.util.Locale;
import org.bukkit.World;

@Command(name = "weather")
@Permission("eternalcore.weather")
class WeatherCommand {

private final NoticeService noticeService;
private final WeatherService weatherService;

@Inject
WeatherCommand(NoticeService noticeService, WeatherService weatherService) {
this.noticeService = noticeService;
this.weatherService = weatherService;
}

@Execute
@DescriptionDocs(description = "Sets weather in current world", arguments = "<sun|rain|thunder> [-p]")
void execute(@Sender Viewer viewer, @Context World world, @Arg WeatherType weatherType, @Flag("-p") boolean persistent) {
this.setWeather(viewer, world, weatherType, persistent);
}

@Execute
@DescriptionDocs(description = "Sets weather in specified world", arguments = "<sun|rain|thunder> <world> [-p]")
void execute(
@Sender Viewer viewer,
@Arg WeatherType weatherType,
@Arg World world,
@Flag("-p") boolean persistent
) {
this.setWeather(viewer, world, weatherType, persistent);
}

@Execute(name = "clear")
@DescriptionDocs(description = "Enables natural weather cycle in current world")
void clearCurrentWorld(@Sender Viewer viewer, @Context World world) {
this.clearWeather(viewer, world);
}

@Execute(name = "clear")
@DescriptionDocs(description = "Enables natural weather cycle in specified world", arguments = "<world>")
void clearSelectedWorld(@Sender Viewer viewer, @Arg World world) {
this.clearWeather(viewer, world);
}

private void setWeather(Viewer viewer, World world, WeatherType weatherType, boolean persistent) {
this.weatherService.setWeather(world, weatherType, persistent);

this.noticeService.create()
.viewer(viewer)
.placeholder("{WORLD}", world.getName())
.notice(translation -> switch (weatherType) {
case SUN -> translation.timeAndWeather().weatherSetSun();
case RAIN -> translation.timeAndWeather().weatherSetRain();
case THUNDER -> translation.timeAndWeather().weatherSetThunder();
})
.send();

if (!persistent) {
return;
}

this.noticeService.create()
.viewer(viewer)
.placeholder("{WORLD}", world.getName())
.placeholder("{WEATHER}", weatherType.name().toLowerCase(Locale.ROOT))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Using weatherType.name().toLowerCase(Locale.ROOT) for the {WEATHER} placeholder may lead to localization issues. In many languages (like Polish), the weather type needs to be a specific noun or adjective that agrees grammatically with the rest of the sentence (e.g., gender or case agreement). Hardcoding the enum name prevents proper translation of this part of the message.

.notice(translation -> translation.timeAndWeather().weatherPersistenceEnabled())
.send();
}

private void clearWeather(Viewer viewer, World world) {
this.weatherService.clearPersistentWeather(world);

this.noticeService.create()
.viewer(viewer)
.placeholder("{WORLD}", world.getName())
.notice(translation -> translation.timeAndWeather().weatherPersistenceDisabled())
.send();
}
Comment on lines +84 to +92
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The /weather clear command currently only re-enables the natural weather cycle but does not change the current weather state. In vanilla Minecraft, /weather clear is used to set the weather to sunny. This discrepancy might be confusing for players who expect the rain to stop immediately. Consider making this command also set the weather to SUN to align with vanilla expectations.


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.eternalcode.core.feature.weather;

import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.injector.annotations.component.Service;
import org.bukkit.GameRule;
import org.bukkit.World;

@Service
class WeatherService {

private static final int DEFAULT_CLEAR_WEATHER_DURATION = 20 * 60 * 10;

private final MinecraftScheduler scheduler;

@Inject
WeatherService(MinecraftScheduler scheduler) {
this.scheduler = scheduler;
}

void setWeather(World world, WeatherType weatherType, boolean persistent) {
this.scheduler.run(() -> {
this.applyWeather(world, weatherType);
world.setGameRule(GameRule.DO_WEATHER_CYCLE, !persistent);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid forcing weather cycle on every non-persistent set

WeatherService#setWeather now always writes DO_WEATHER_CYCLE to true when persistent is false, and all legacy /sun, /rain, and /thunder commands call this path with false. That introduces a regression where using those commands silently re-enables the weather cycle in worlds that were intentionally locked (by config, gamerule, or a prior /weather -p), changing global world behavior beyond just setting the current weather. Consider only changing DO_WEATHER_CYCLE when the user explicitly requests persistence changes (-p or clear).

Useful? React with 👍 / 👎.

});
}
Comment on lines +21 to +26
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The current implementation of setWeather always updates the DO_WEATHER_CYCLE gamerule. If persistent is false, it explicitly sets it to true. This can unintentionally overwrite a global server setting where an administrator has disabled the weather cycle for other reasons (e.g., a static clear-sky world). It is safer to only modify the gamerule when persistence is explicitly requested, and let the /weather clear command handle re-enabling the cycle.


void clearPersistentWeather(World world) {
this.scheduler.run(() -> world.setGameRule(GameRule.DO_WEATHER_CYCLE, true));
}

private void applyWeather(World world, WeatherType weatherType) {
switch (weatherType) {
case SUN -> {
world.setClearWeatherDuration(DEFAULT_CLEAR_WEATHER_DURATION);
world.setStorm(false);
world.setThundering(false);
}
case RAIN -> {
world.setStorm(true);
world.setThundering(false);
}
case THUNDER -> {
world.setStorm(true);
world.setThundering(true);
}
default -> throw new IllegalStateException("Unsupported weather type: " + weatherType);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.eternalcode.core.feature.weather;

public enum WeatherType {
SUN,
RAIN,
THUNDER
}