diff --git a/notes.txt b/notes.txt index 477da42..8995335 100644 --- a/notes.txt +++ b/notes.txt @@ -62,3 +62,11 @@ solution? for now let's warn and update time every tick to check: scale * floor(72/scale) == 72 + +goal: offsetting by player position + +t = (longitude / 15) * 1000 * scale + +accounting for sunrise and sunset +TODO, idk yet without + diff --git a/src/main/java/eu/m724/realweather/RealWeatherPlugin.java b/src/main/java/eu/m724/realweather/RealWeatherPlugin.java index c9d5ecc..1c7db0c 100644 --- a/src/main/java/eu/m724/realweather/RealWeatherPlugin.java +++ b/src/main/java/eu/m724/realweather/RealWeatherPlugin.java @@ -12,6 +12,7 @@ import org.bukkit.plugin.java.JavaPlugin; import com.google.common.base.Charsets; import eu.m724.realweather.commands.GeoCommand; +import eu.m724.realweather.commands.LocalTimeCommand; import eu.m724.realweather.mapper.Mapper; import eu.m724.realweather.mapper.MapperConfig; import eu.m724.realweather.mapper.MapperEventHandler; @@ -30,11 +31,8 @@ public class RealWeatherPlugin extends JavaPlugin { private ThunderMaster thunderMaster; private TimeMaster timeMaster; - private YamlConfiguration config; private Logger logger; - private YamlConfiguration mapConfig; - @Override public void onEnable() { logger = getLogger(); @@ -115,6 +113,9 @@ public class RealWeatherPlugin extends JavaPlugin { } getCommand("geo").setExecutor(new GeoCommand()); + + if (GlobalConstants.timeConfig.enabled) + getCommand("localtime").setExecutor(new LocalTimeCommand()); DebugLogger.info("ended loading", 1); } diff --git a/src/main/java/eu/m724/realweather/commands/GeoCommand.java b/src/main/java/eu/m724/realweather/commands/GeoCommand.java index 2578f12..874befa 100644 --- a/src/main/java/eu/m724/realweather/commands/GeoCommand.java +++ b/src/main/java/eu/m724/realweather/commands/GeoCommand.java @@ -37,7 +37,7 @@ public class GeoCommand implements CommandExecutor { } } else if (args.length >= 2) { double latitude = Double.parseDouble(args[0]); - double longitude = Double.parseDouble(args[0]); + double longitude = Double.parseDouble(args[1]); Coordinates coordinates = new Coordinates(latitude, longitude); Location location = GlobalConstants.getMapper().coordinatesToLocation(player.getWorld(), coordinates); diff --git a/src/main/java/eu/m724/realweather/commands/LocalTimeCommand.java b/src/main/java/eu/m724/realweather/commands/LocalTimeCommand.java new file mode 100644 index 0000000..d7bb8f0 --- /dev/null +++ b/src/main/java/eu/m724/realweather/commands/LocalTimeCommand.java @@ -0,0 +1,73 @@ +package eu.m724.realweather.commands; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalUnit; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import eu.m724.realweather.GlobalConstants; +import eu.m724.realweather.mapper.Mapper; +import eu.m724.realweather.time.TimeConfig; +import eu.m724.wtapi.object.Coordinates; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ComponentBuilder; + +public class LocalTimeCommand implements CommandExecutor { + private TimeConfig timeConfig = GlobalConstants.getTimeConfig(); + private Mapper mapper = GlobalConstants.getMapper(); + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + Player player = sender instanceof Player ? (Player) sender : null; + + long worldTime = timeConfig.calculateWorldTimeSeconds(); + Duration worldTimeDuration = Duration.ofSeconds(worldTime); + + String worldTimeFormatted = String.format("%d:%02d:%02d", + worldTimeDuration.toHours(), + worldTimeDuration.toMinutesPart(), + worldTimeDuration.toSecondsPart()); + + BaseComponent[] component = new ComponentBuilder("World time: ").color(ChatColor.GRAY) + .append(worldTimeFormatted).color(ChatColor.DARK_AQUA) + .create(); + + sender.spigot().sendMessage(component); + + if (timeConfig.dynamic && player != null && player.hasPermission("realweather.dynamic")) { + Coordinates coordinates = mapper.locationToCoordinates(player.getLocation()); + + long offsetTime = timeConfig.calculateTimeOffsetSeconds(coordinates.longitude); + boolean negative = offsetTime < 0; + + Duration localTimeDuration = worldTimeDuration.plus(offsetTime, ChronoUnit.SECONDS); + Duration offsetTimeDuration = Duration.ofSeconds(negative ? -offsetTime : offsetTime); + + String offsetTimeFormatted = String.format("%s%d:%02d:%02d", + (negative ? "-" : "+"), + offsetTimeDuration.toHours(), + offsetTimeDuration.toMinutesPart(), + offsetTimeDuration.toSecondsPart()); + + String localTimeFormatted = String.format("%d:%02d:%02d", + localTimeDuration.toHours(), + localTimeDuration.toMinutesPart(), + localTimeDuration.toSecondsPart()); + + component = new ComponentBuilder("Local time: ").color(ChatColor.GOLD) + .append(localTimeFormatted).color(ChatColor.AQUA) + .append(" " + offsetTimeFormatted).color(ChatColor.GRAY) + .create(); + + sender.spigot().sendMessage(component); + } + + return true; + } + +} diff --git a/src/main/java/eu/m724/realweather/mapper/Mapper.java b/src/main/java/eu/m724/realweather/mapper/Mapper.java index f1b1a08..1ef8966 100644 --- a/src/main/java/eu/m724/realweather/mapper/Mapper.java +++ b/src/main/java/eu/m724/realweather/mapper/Mapper.java @@ -1,8 +1,13 @@ package eu.m724.realweather.mapper; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.function.Consumer; +import org.bukkit.GameRule; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.plugin.Plugin; @@ -13,10 +18,35 @@ public class Mapper { private MapperConfig config; private List worlds = new ArrayList<>(); + private List> worldLoadConsumers = new ArrayList<>(); + private List> worldUnloadConsumers = new ArrayList<>(); + // TODO game rules + public Mapper(MapperConfig config) { this.config = config; } + /** + * Registers a consumer which will be called on world load + * @param consumer + */ + public void registerWorldLoadConsumer(Consumer consumer) { + this.worldLoadConsumers.add(consumer); + } + + /** + * Registers a consumer which will be called on world unload + * @param consumer + */ + public void registerWorldUnloadConsumer(Consumer consumer) { + this.worldUnloadConsumers.add(consumer); + } + + /** + * Registers events handled by mapper. + * This should be called once on plugin load. + * @param plugin + */ public void registerEvents(Plugin plugin) { plugin.getServer().getPluginManager().registerEvents(new MapperEventHandler(this), plugin); } @@ -29,8 +59,8 @@ public class Mapper { } public Location coordinatesToLocation(World world, Coordinates coordinates) { - double x = -coordinates.latitude * config.scaleLatitude; - double z = coordinates.longitude * config.scaleLongitude; + double x = coordinates.longitude * config.scaleLongitude; + double z = -coordinates.latitude * config.scaleLatitude; return new Location(world, x, 0, z); @@ -47,14 +77,18 @@ public class Mapper { boolean loadWorld(World world) { boolean loaded = config.worlds.contains(world.getName()) ^ config.worldBlacklist; - if (loaded) + if (loaded) { worlds.add(world); + worldLoadConsumers.forEach(consumer -> consumer.accept(world)); + } return loaded; } void unloadWorld(World world) { - worlds.remove(world); + if (worlds.remove(world)) { + worldUnloadConsumers.forEach(consumer -> consumer.accept(world)); + } } } diff --git a/src/main/java/eu/m724/realweather/time/AsyncPlayerTimeTask.java b/src/main/java/eu/m724/realweather/time/AsyncPlayerTimeTask.java index 5cc5666..36d1ea0 100644 --- a/src/main/java/eu/m724/realweather/time/AsyncPlayerTimeTask.java +++ b/src/main/java/eu/m724/realweather/time/AsyncPlayerTimeTask.java @@ -4,6 +4,7 @@ import org.bukkit.Server; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import eu.m724.realweather.DebugLogger; import eu.m724.realweather.GlobalConstants; import eu.m724.realweather.mapper.Mapper; import eu.m724.realweather.weather.PlayerWeatherDirectory; @@ -27,15 +28,10 @@ public class AsyncPlayerTimeTask extends BukkitRunnable { for (Player player : server.getOnlinePlayers()) { if (!player.hasPermission("realweather.dynamic")) continue; - Weather weather = playerWeatherDirectory.getWeather(player); - - if (weather != null) { - // TODO sunrise sunset - } - Coordinates coordinates = mapper.locationToCoordinates(player.getLocation()); long offsetTicks = (long) ((coordinates.longitude / 15) * 1000 * timeConfig.scale); player.setPlayerTime(offsetTicks, true); // TODO can this be negative? + DebugLogger.info("Time for %s: %d", 2, player.getName(), offsetTicks); } } } diff --git a/src/main/java/eu/m724/realweather/time/SyncTimeUpdateTask.java b/src/main/java/eu/m724/realweather/time/SyncTimeUpdateTask.java index d23be32..da46348 100644 --- a/src/main/java/eu/m724/realweather/time/SyncTimeUpdateTask.java +++ b/src/main/java/eu/m724/realweather/time/SyncTimeUpdateTask.java @@ -2,6 +2,7 @@ package eu.m724.realweather.time; import org.bukkit.scheduler.BukkitRunnable; +import eu.m724.realweather.DebugLogger; import eu.m724.realweather.GlobalConstants; import eu.m724.realweather.mapper.Mapper; @@ -16,10 +17,10 @@ public class SyncTimeUpdateTask extends BukkitRunnable { @Override public void run() { // TODO double? - long now = (long) (System.currentTimeMillis() * timeConfig.scale / 1000); - long time = Math.floorMod(now % 86400 / 72 * 20 - 6000, 24000); + long ticks = timeConfig.calculateWorldTimeTicks(); + DebugLogger.info("Updating time: %d", 2, ticks); - mapper.getWorlds().forEach(world -> world.setFullTime(time)); + mapper.getWorlds().forEach(world -> world.setFullTime(ticks)); // TODO add world handlers to mapper and don't calculate time each run } diff --git a/src/main/java/eu/m724/realweather/time/TimeConfig.java b/src/main/java/eu/m724/realweather/time/TimeConfig.java index c4f2168..f9b9980 100644 --- a/src/main/java/eu/m724/realweather/time/TimeConfig.java +++ b/src/main/java/eu/m724/realweather/time/TimeConfig.java @@ -20,4 +20,34 @@ public class TimeConfig { return timeConfig; } + + public long calculateWorldTimeSeconds() { + long now = (long) (System.currentTimeMillis() * scale / 1000) % 86400; + + return now; + } + + public long calculateWorldTimeTicks() { + long now = calculateWorldTimeSeconds(); + long ticks = Math.floorMod(now / 72 * 20 - 6000, 24000); + + return ticks; + } + + /** + * this method is mostly for info + * @param longitude + * @return + */ + public long calculateTimeOffsetSeconds(double longitude) { + long offset = (long) ((longitude / 15) * 3600 * scale); + + return offset; + } + + public long calculateTimeOffsetTicks(double longitude) { + long offsetTicks = (long) ((longitude / 15) * 1000 * scale); + + return offsetTicks; + } } diff --git a/src/main/java/eu/m724/realweather/time/TimeMaster.java b/src/main/java/eu/m724/realweather/time/TimeMaster.java index 110f1ce..ace14c6 100644 --- a/src/main/java/eu/m724/realweather/time/TimeMaster.java +++ b/src/main/java/eu/m724/realweather/time/TimeMaster.java @@ -1,19 +1,21 @@ package eu.m724.realweather.time; +import org.bukkit.GameRule; import org.bukkit.plugin.Plugin; import eu.m724.realweather.DebugLogger; import eu.m724.realweather.GlobalConstants; +import eu.m724.realweather.commands.LocalTimeCommand; import eu.m724.realweather.mapper.Mapper; import eu.m724.realweather.object.UserException; public class TimeMaster { - private TimeConfig config; + private TimeConfig timeConfig; private Mapper mapper = GlobalConstants.getMapper(); private Plugin plugin = GlobalConstants.getPlugin(); - public TimeMaster(TimeConfig config) { - this.config = config; + public TimeMaster(TimeConfig timeConfig) { + this.timeConfig = timeConfig; } /** @@ -21,21 +23,27 @@ public class TimeMaster { * @throws UserException config issue */ public void init() throws UserException { - if (!config.enabled) + if (!timeConfig.enabled) return; - long period = (long) (72 / config.scale); + long period = (long) (72 / timeConfig.scale); - if (config.scale * Math.floor(period) == 72) { + if (timeConfig.scale * Math.floor(period) != 72.0) { // TODO log this properly DebugLogger.info("Warning: RealTime scale is not optimal. Time will be out of sync.", 0); } - new SyncTimeUpdateTask(config).runTaskTimer(plugin, 0, period); - new AsyncPlayerTimeTask(config).runTaskTimerAsynchronously(plugin, 0, period); // TODO maybe use a different period? - // TODO also make it on player join + new SyncTimeUpdateTask(timeConfig).runTaskTimer(plugin, 0, period); - DebugLogger.info("time loaded", 1); + if (timeConfig.dynamic) + new AsyncPlayerTimeTask(timeConfig).runTaskTimerAsynchronously(plugin, 0, period); + // TODO maybe use a different period? + // TODO also make it on player join + + mapper.registerWorldLoadConsumer(world -> world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false)); + mapper.registerWorldUnloadConsumer(world -> world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, true)); + + DebugLogger.info("time loaded, update every %d ticks", 1, period); } } diff --git a/src/main/java/eu/m724/realweather/weather/WeatherMaster.java b/src/main/java/eu/m724/realweather/weather/WeatherMaster.java index 6e92a2d..5836bde 100644 --- a/src/main/java/eu/m724/realweather/weather/WeatherMaster.java +++ b/src/main/java/eu/m724/realweather/weather/WeatherMaster.java @@ -1,5 +1,6 @@ package eu.m724.realweather.weather; +import org.bukkit.GameRule; import org.bukkit.plugin.Plugin; import eu.m724.realweather.DebugLogger; @@ -40,6 +41,9 @@ public class WeatherMaster { retriever.runTaskAsynchronously(plugin); plugin.getServer().getPluginManager().registerEvents(retriever, plugin); + mapper.registerWorldLoadConsumer(world -> world.setGameRule(GameRule.DO_WEATHER_CYCLE, false)); + mapper.registerWorldUnloadConsumer(world -> world.setGameRule(GameRule.DO_WEATHER_CYCLE, true)); + DebugLogger.info("weather loaded", 1); } diff --git a/src/main/resources/modules/time.yml b/src/main/resources/modules/time.yml index b95c34e..4140160 100644 --- a/src/main/resources/modules/time.yml +++ b/src/main/resources/modules/time.yml @@ -11,7 +11,7 @@ enabled: false # settings for both are in map.yml dynamic: true -# x day cycles in 1 irl day cycle +# x in game day cycles in 1 irl day cycle # time will no longer be in sync # can be decimal -modifier: 1.0 \ No newline at end of file +scale: 1.0 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index bd35151..85e55d9 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -20,6 +20,10 @@ commands: permission: realweather.geo permission-message: You do not have permission to use this command. # usage is processed in code + localtime: + description: Get real time in current location + permission: realweather.localtime + permission-message: You do not have permission to use this command. permissions: realweather.command: @@ -39,13 +43,16 @@ permissions: realweather.geo.tp: description: Allows teleportation using /geo + realweather.localtime: + description: Allows /localtime + default: true + realweather.dynamic: description: Includes player in dynamic conditions default: true realweather.actionbar: description: Displays status on player's action bar - default: op realweather.update.notify: description: Receive notifications for RealWeather updates \ No newline at end of file