work
This commit is contained in:
		
					parent
					
						
							
								163c9bd71d
							
						
					
				
			
			
				commit
				
					
						18b7df1650
					
				
			
		
					 12 changed files with 276 additions and 81 deletions
				
			
		
							
								
								
									
										9
									
								
								pom.xml
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								pom.xml
									
										
									
									
									
								
							| 
						 | 
					@ -33,7 +33,7 @@
 | 
				
			||||||
		<dependency>
 | 
							<dependency>
 | 
				
			||||||
			<groupId>eu.m724</groupId>
 | 
								<groupId>eu.m724</groupId>
 | 
				
			||||||
		    <artifactId>wtapi</artifactId>
 | 
							    <artifactId>wtapi</artifactId>
 | 
				
			||||||
		    <version>0.8.0</version>
 | 
							    <version>0.8.3</version>
 | 
				
			||||||
		</dependency>
 | 
							</dependency>
 | 
				
			||||||
		<dependency>
 | 
							<dependency>
 | 
				
			||||||
			<groupId>eu.m724</groupId>
 | 
								<groupId>eu.m724</groupId>
 | 
				
			||||||
| 
						 | 
					@ -46,6 +46,13 @@
 | 
				
			||||||
			<version>3.0.3</version>
 | 
								<version>3.0.3</version>
 | 
				
			||||||
			<scope>compile</scope>
 | 
								<scope>compile</scope>
 | 
				
			||||||
		</dependency>
 | 
							</dependency>
 | 
				
			||||||
 | 
							<!-- https://mvnrepository.com/artifact/junit/junit -->
 | 
				
			||||||
 | 
							<dependency>
 | 
				
			||||||
 | 
								<groupId>junit</groupId>
 | 
				
			||||||
 | 
								<artifactId>junit</artifactId>
 | 
				
			||||||
 | 
								<version>4.13.2</version>
 | 
				
			||||||
 | 
								<scope>test</scope>
 | 
				
			||||||
 | 
							</dependency>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	</dependencies>
 | 
						</dependencies>
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,10 @@
 | 
				
			||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<module version="4">
 | 
					<module version="4">
 | 
				
			||||||
 | 
					  <component name="AdditionalModuleElements">
 | 
				
			||||||
 | 
					    <content url="file://$MODULE_DIR$" dumb="true">
 | 
				
			||||||
 | 
					      <sourceFolder url="file://$MODULE_DIR$/src/main/test" isTestSource="true" />
 | 
				
			||||||
 | 
					    </content>
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
  <component name="FacetManager">
 | 
					  <component name="FacetManager">
 | 
				
			||||||
    <facet type="minecraft" name="Minecraft">
 | 
					    <facet type="minecraft" name="Minecraft">
 | 
				
			||||||
      <configuration>
 | 
					      <configuration>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,7 +135,7 @@ public class RealWeatherPlugin extends JavaPlugin {
 | 
				
			||||||
		getCommand("rwadmin").setExecutor(new AdminCommand(updater));
 | 
							getCommand("rwadmin").setExecutor(new AdminCommand(updater));
 | 
				
			||||||
		getCommand("geo").setExecutor(new GeoCommand());
 | 
							getCommand("geo").setExecutor(new GeoCommand());
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (GlobalConstants.timeConfig.enabled)
 | 
							if (GlobalConstants.timeConfig.enabled())
 | 
				
			||||||
			getCommand("localtime").setExecutor(new LocalTimeCommand());
 | 
								getCommand("localtime").setExecutor(new LocalTimeCommand());
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (GlobalConstants.weatherConfig.enabled)
 | 
							if (GlobalConstants.weatherConfig.enabled)
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ public class RealWeatherPlugin extends JavaPlugin {
 | 
				
			||||||
				GlobalConstants.thunderConfig.enabled ? GlobalConstants.thunderConfig.provider : "off"
 | 
									GlobalConstants.thunderConfig.enabled ? GlobalConstants.thunderConfig.provider : "off"
 | 
				
			||||||
		));
 | 
							));
 | 
				
			||||||
		metrics.addCustomChart(new SimplePie("real_time", () ->
 | 
							metrics.addCustomChart(new SimplePie("real_time", () ->
 | 
				
			||||||
				GlobalConstants.timeConfig.enabled ? "on" : "off"
 | 
									GlobalConstants.timeConfig.enabled() ? "on" : "off"
 | 
				
			||||||
		));
 | 
							));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		DebugLogger.info("ended loading", 1);
 | 
							DebugLogger.info("ended loading", 1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,13 +63,13 @@ public class AdminCommand implements CommandExecutor {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		componentBuilder.append("\nTime: ").color(ChatColor.GOLD);
 | 
							componentBuilder.append("\nTime: ").color(ChatColor.GOLD);
 | 
				
			||||||
		componentBuilder.append(timeConfig.enabled ? enabledComponent : disabledComponent);
 | 
							componentBuilder.append(timeConfig.enabled() ? enabledComponent : disabledComponent);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (timeConfig.enabled) {
 | 
							if (timeConfig.enabled()) {
 | 
				
			||||||
			componentBuilder.append(" Scale: ").color(ChatColor.GOLD);
 | 
								componentBuilder.append(" Scale: ").color(ChatColor.GOLD);
 | 
				
			||||||
			componentBuilder.append(Double.toString(timeConfig.scale) + "\n").color(ChatColor.AQUA);
 | 
								componentBuilder.append(Double.toString(timeConfig.scale()) + "\n").color(ChatColor.AQUA);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			long worldTime = timeConfig.calculateWorldTimeSeconds();
 | 
								long worldTime = 0; // TODO timeConfig.calculateWorldTimeSeconds();
 | 
				
			||||||
			Duration worldTimeDuration = Duration.ofSeconds(worldTime);
 | 
								Duration worldTimeDuration = Duration.ofSeconds(worldTime);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			String worldTimeFormatted = String.format("%d:%02d:%02d\n",
 | 
								String worldTimeFormatted = String.format("%d:%02d:%02d\n",
 | 
				
			||||||
| 
						 | 
					@ -81,7 +81,7 @@ public class AdminCommand implements CommandExecutor {
 | 
				
			||||||
			componentBuilder.append(worldTimeFormatted).color(ChatColor.AQUA);
 | 
								componentBuilder.append(worldTimeFormatted).color(ChatColor.AQUA);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			componentBuilder.append(" Dynamic: ").color(ChatColor.GOLD);
 | 
								componentBuilder.append(" Dynamic: ").color(ChatColor.GOLD);
 | 
				
			||||||
			componentBuilder.append(timeConfig.dynamic ? enabledComponent : disabledComponent);
 | 
								componentBuilder.append(timeConfig.dynamic() ? enabledComponent : disabledComponent);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		componentBuilder.append("\nThunder: ").color(ChatColor.GOLD);
 | 
							componentBuilder.append("\nThunder: ").color(ChatColor.GOLD);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ public class LocalTimeCommand implements CommandExecutor {
 | 
				
			||||||
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
 | 
						public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
 | 
				
			||||||
		Player player = sender instanceof Player ? (Player) sender : null;
 | 
							Player player = sender instanceof Player ? (Player) sender : null;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		long worldTime = timeConfig.calculateWorldTimeSeconds();
 | 
							long worldTime = 0; // TODO timeConfig.calculateWorldTimeSeconds();
 | 
				
			||||||
		Duration worldTimeDuration = Duration.ofSeconds(worldTime);
 | 
							Duration worldTimeDuration = Duration.ofSeconds(worldTime);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		String worldTimeFormatted = String.format("%d:%02d:%02d",
 | 
							String worldTimeFormatted = String.format("%d:%02d:%02d",
 | 
				
			||||||
| 
						 | 
					@ -37,10 +37,10 @@ public class LocalTimeCommand implements CommandExecutor {
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		sender.spigot().sendMessage(component);
 | 
							sender.spigot().sendMessage(component);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (timeConfig.dynamic && player != null && player.hasPermission("realweather.dynamic")) {
 | 
							if (timeConfig.dynamic() && player != null && player.hasPermission("realweather.dynamic")) {
 | 
				
			||||||
			Coordinates coordinates = mapper.locationToCoordinates(player.getLocation());
 | 
								Coordinates coordinates = mapper.locationToCoordinates(player.getLocation());
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			long offsetTime = timeConfig.calculateTimeOffsetSeconds(coordinates.longitude);
 | 
								long offsetTime = 0; // TODO timeConfig.calculateTimeOffsetSeconds(coordinates.longitude);
 | 
				
			||||||
			boolean negative = offsetTime < 0;
 | 
								boolean negative = offsetTime < 0;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			Duration localTimeDuration = worldTimeDuration.plus(offsetTime, ChronoUnit.SECONDS);
 | 
								Duration localTimeDuration = worldTimeDuration.plus(offsetTime, ChronoUnit.SECONDS);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,12 +10,14 @@ import eu.m724.realweather.mapper.Mapper;
 | 
				
			||||||
import eu.m724.wtapi.object.Coordinates;
 | 
					import eu.m724.wtapi.object.Coordinates;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class AsyncPlayerTimeTask extends BukkitRunnable {
 | 
					public class AsyncPlayerTimeTask extends BukkitRunnable {
 | 
				
			||||||
	private Server server = GlobalConstants.getPlugin().getServer();
 | 
						private final Server server = GlobalConstants.getPlugin().getServer();
 | 
				
			||||||
	private Mapper mapper = GlobalConstants.getMapper();
 | 
						private final Mapper mapper = GlobalConstants.getMapper();
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	private TimeConfig timeConfig;
 | 
						private final TimeConverter timeConverter;
 | 
				
			||||||
 | 
						private final TimeConfig timeConfig;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	AsyncPlayerTimeTask(TimeConfig timeConfig) {
 | 
						AsyncPlayerTimeTask(TimeConverter timeConverter, TimeConfig timeConfig) {
 | 
				
			||||||
 | 
							this.timeConverter = timeConverter;
 | 
				
			||||||
		this.timeConfig = timeConfig;
 | 
							this.timeConfig = timeConfig;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,9 +26,22 @@ public class AsyncPlayerTimeTask extends BukkitRunnable {
 | 
				
			||||||
		for (Player player : server.getOnlinePlayers()) {
 | 
							for (Player player : server.getOnlinePlayers()) {
 | 
				
			||||||
			if (!player.hasPermission("realweather.dynamic")) continue;
 | 
								if (!player.hasPermission("realweather.dynamic")) continue;
 | 
				
			||||||
			if (!mapper.getWorlds().contains(player.getWorld())) continue;
 | 
								if (!mapper.getWorlds().contains(player.getWorld())) continue;
 | 
				
			||||||
			
 | 
					
 | 
				
			||||||
			Coordinates coordinates = mapper.locationToCoordinates(player.getLocation());
 | 
								Coordinates coordinates = mapper.locationToCoordinates(player.getLocation());
 | 
				
			||||||
			long offsetTicks = timeConfig.calculateTimeOffsetTicks(coordinates.longitude);
 | 
					
 | 
				
			||||||
 | 
								long time = System.currentTimeMillis();
 | 
				
			||||||
 | 
								time = timeConverter.scale(time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (timeConfig.twilight()) {
 | 
				
			||||||
 | 
									time = timeConverter.offsetTwilight(time, mapper.getPoint());
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								time = timeConverter.calculateZoneOffset(coordinates.longitude);
 | 
				
			||||||
 | 
								long ticks = timeConverter.millisToTicks(time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								long offsetTicks = timeConverter.calculateZoneOffset(coordinates.longitude);
 | 
				
			||||||
 | 
								offsetTicks = timeConverter.millisToTicks(offsetTicks);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			player.setPlayerTime(Math.floorMod(offsetTicks, 24000), true);
 | 
								player.setPlayerTime(Math.floorMod(offsetTicks, 24000), true);
 | 
				
			||||||
			DebugLogger.info("Time for %s: %d", 2, player.getName(), offsetTicks);
 | 
								DebugLogger.info("Time for %s: %d", 2, player.getName(), offsetTicks);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
package eu.m724.realweather.time;
 | 
					package eu.m724.realweather.time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import eu.m724.wtapi.object.Coordinates;
 | 
				
			||||||
import org.bukkit.scheduler.BukkitRunnable;
 | 
					import org.bukkit.scheduler.BukkitRunnable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import eu.m724.realweather.DebugLogger;
 | 
					import eu.m724.realweather.DebugLogger;
 | 
				
			||||||
| 
						 | 
					@ -7,17 +8,26 @@ import eu.m724.realweather.GlobalConstants;
 | 
				
			||||||
import eu.m724.realweather.mapper.Mapper;
 | 
					import eu.m724.realweather.mapper.Mapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class SyncTimeUpdateTask extends BukkitRunnable {
 | 
					public class SyncTimeUpdateTask extends BukkitRunnable {
 | 
				
			||||||
	private TimeConfig timeConfig;
 | 
						private final Mapper mapper = GlobalConstants.getMapper();
 | 
				
			||||||
	private Mapper mapper = GlobalConstants.getMapper();
 | 
					
 | 
				
			||||||
	
 | 
						private final TimeConverter timeConverter;
 | 
				
			||||||
	SyncTimeUpdateTask(TimeConfig timeConfig) {
 | 
						private final TimeConfig timeConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SyncTimeUpdateTask(TimeConverter timeConverter, TimeConfig timeConfig) {
 | 
				
			||||||
 | 
							this.timeConverter = timeConverter;
 | 
				
			||||||
		this.timeConfig = timeConfig;
 | 
							this.timeConfig = timeConfig;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public void run() {
 | 
						public void run() {
 | 
				
			||||||
		// TODO double?
 | 
							long time = System.currentTimeMillis();
 | 
				
			||||||
		long ticks = timeConfig.calculateWorldTimeTicks();
 | 
							time = timeConverter.scale(time);
 | 
				
			||||||
 | 
							if (timeConfig.twilight()) {
 | 
				
			||||||
 | 
								time = timeConverter.offsetTwilight(time, mapper.getPoint());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							long ticks = timeConverter.millisToTicks(time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		DebugLogger.info("Updating time: %d", 2, ticks);
 | 
							DebugLogger.info("Updating time: %d", 2, ticks);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		mapper.getWorlds().forEach(world -> world.setFullTime(ticks));
 | 
							mapper.getWorlds().forEach(world -> world.setFullTime(ticks));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,54 +2,23 @@ package eu.m724.realweather.time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.bukkit.configuration.ConfigurationSection;
 | 
					import org.bukkit.configuration.ConfigurationSection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class TimeConfig {
 | 
					import java.util.UUID;
 | 
				
			||||||
	public boolean enabled;
 | 
					
 | 
				
			||||||
	
 | 
					public record TimeConfig(
 | 
				
			||||||
	// state is per player
 | 
							boolean enabled,
 | 
				
			||||||
	public boolean dynamic;
 | 
					
 | 
				
			||||||
	public boolean twilight;
 | 
							boolean dynamic,
 | 
				
			||||||
	// x day cycles in 1 irl day
 | 
							boolean twilight,
 | 
				
			||||||
	public double scale;
 | 
					
 | 
				
			||||||
	
 | 
							double scale
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
	public static TimeConfig fromConfiguration(ConfigurationSection configuration) {
 | 
						public static TimeConfig fromConfiguration(ConfigurationSection configuration) {
 | 
				
			||||||
		TimeConfig timeConfig = new TimeConfig();
 | 
							boolean enabled = configuration.getBoolean("enabled");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							boolean dynamic = configuration.getBoolean("dynamic");
 | 
				
			||||||
 | 
							boolean twilight = configuration.getBoolean("twilight");
 | 
				
			||||||
 | 
							double scale = configuration.getDouble("scale");
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		timeConfig.enabled = configuration.getBoolean("enabled");
 | 
							return new TimeConfig(enabled, dynamic, twilight, scale);
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		timeConfig.dynamic = configuration.getBoolean("dynamic");
 | 
					 | 
				
			||||||
		timeConfig.twilight = configuration.getBoolean("twilight");
 | 
					 | 
				
			||||||
		timeConfig.scale = configuration.getDouble("scale");
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		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;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										148
									
								
								src/main/java/eu/m724/realweather/time/TimeConverter.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/main/java/eu/m724/realweather/time/TimeConverter.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,148 @@
 | 
				
			||||||
 | 
					package eu.m724.realweather.time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import eu.m724.wtapi.object.Coordinates;
 | 
				
			||||||
 | 
					import eu.m724.wtapi.object.Twilight;
 | 
				
			||||||
 | 
					import eu.m724.wtapi.object.TwilightCalendar;
 | 
				
			||||||
 | 
					import eu.m724.wtapi.provider.twilight.TwilightTimeCache;
 | 
				
			||||||
 | 
					import eu.m724.wtapi.provider.twilight.TwilightTimeProvider;
 | 
				
			||||||
 | 
					import eu.m724.wtapi.provider.twilight.impl.approximate.ApproximateTwilightTimeCache;
 | 
				
			||||||
 | 
					import eu.m724.wtapi.provider.twilight.impl.approximate.ApproximateTwilightTimeProvider;
 | 
				
			||||||
 | 
					import org.checkerframework.checker.units.qual.A;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.Duration;
 | 
				
			||||||
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.time.LocalDate;
 | 
				
			||||||
 | 
					import java.time.ZoneOffset;
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TimeConverter {
 | 
				
			||||||
 | 
					    public final double scale;
 | 
				
			||||||
 | 
					    // TODO make this configurable
 | 
				
			||||||
 | 
					    private final ApproximateTwilightTimeProvider provider = new ApproximateTwilightTimeProvider();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TimeConverter(double scale) {
 | 
				
			||||||
 | 
					        this.scale = scale;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Divides time by predefined scale<br>
 | 
				
			||||||
 | 
					     * ...slowing it down
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param time unix milliseconds
 | 
				
			||||||
 | 
					     * @return scaled unix milliseconds
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public long scale(long time) {
 | 
				
			||||||
 | 
					        return (long) (time / scale);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Converts unix timestamp to in game ticks
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param time unix millis
 | 
				
			||||||
 | 
					     * @return in-game ticks
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public long millisToTicks(long time) {
 | 
				
			||||||
 | 
					        return Math.floorMod(time / 3600 - 6000, 24000);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Calculates how often (or how rarely) we can update time<br>
 | 
				
			||||||
 | 
					     * That is, to not do stuff when we don't have to<br>
 | 
				
			||||||
 | 
					     * In ticks, because it's used with Bukkit scheduler
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return update period IN TICKS
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public long calculateUpdatePeriod() {
 | 
				
			||||||
 | 
					        return (long) (72 / scale);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Calculates time offset (in millis) for specified longitude
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param longitude the longitude
 | 
				
			||||||
 | 
					     * @return milliseconds of offset from the center of the world (0)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public long calculateZoneOffset(double longitude) {
 | 
				
			||||||
 | 
					        return (long) (longitude * 3600000);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO optimize
 | 
				
			||||||
 | 
					    public long offsetTwilight(long unixTimestampMs, Coordinates coordinates) {
 | 
				
			||||||
 | 
					        // Constants
 | 
				
			||||||
 | 
					        final long MILLIS_PER_DAY = 86400000;
 | 
				
			||||||
 | 
					        final long SCALED_SUNRISE_MS = 6 * 3600000;  // 06:00 in milliseconds
 | 
				
			||||||
 | 
					        final long SCALED_SUNSET_MS = 18 * 3600000;  // 18:00 in milliseconds
 | 
				
			||||||
 | 
					        final long SCALED_DAY_LENGTH_MS = SCALED_SUNSET_MS - SCALED_SUNRISE_MS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Convert Unix timestamp to Instant and LocalDate
 | 
				
			||||||
 | 
					        Instant instant = Instant.ofEpochMilli(unixTimestampMs);
 | 
				
			||||||
 | 
					        LocalDate date = LocalDate.ofInstant(instant, ZoneOffset.UTC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get twilight information for the date
 | 
				
			||||||
 | 
					        TwilightCalendar calendar = provider.getCalendar(date);
 | 
				
			||||||
 | 
					        Twilight twilight = calendar.twilight(coordinates);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        System.out.println("Twilight converted date: " + twilight.date());
 | 
				
			||||||
 | 
					        System.out.println("Sunrise: " + twilight.sunrise());
 | 
				
			||||||
 | 
					        System.out.println("Sunset: " + twilight.sunset());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (twilight.isPolarDay()) {
 | 
				
			||||||
 | 
					            long daytime = unixTimestampMs % 86400000;
 | 
				
			||||||
 | 
					            if (daytime < 21600000) {
 | 
				
			||||||
 | 
					                unixTimestampMs += 43200000;
 | 
				
			||||||
 | 
					            } else if (daytime > 64800000) {
 | 
				
			||||||
 | 
					                unixTimestampMs += 43200000;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            System.out.println("Polar day");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return unixTimestampMs;
 | 
				
			||||||
 | 
					        } else if (twilight.isPolarNight()) {
 | 
				
			||||||
 | 
					            long daytime = unixTimestampMs % 86400000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (daytime > 21600000 && daytime < 64800000) {
 | 
				
			||||||
 | 
					                unixTimestampMs += 43200000;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            System.out.println("Polar night");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return unixTimestampMs;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        long sunriseMs = twilight.sunrise().toInstant(ZoneOffset.UTC).toEpochMilli();
 | 
				
			||||||
 | 
					        long sunsetMs = twilight.sunset().toInstant(ZoneOffset.UTC).toEpochMilli();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Handle edge cases
 | 
				
			||||||
 | 
					        if (unixTimestampMs == sunriseMs) return SCALED_SUNRISE_MS;
 | 
				
			||||||
 | 
					        if (unixTimestampMs == sunsetMs) return SCALED_SUNSET_MS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        long startTimeMs, endTimeMs, scaledStartMs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (unixTimestampMs >= sunriseMs && unixTimestampMs < sunsetMs) {
 | 
				
			||||||
 | 
					            // Daytime
 | 
				
			||||||
 | 
					            startTimeMs = sunriseMs;
 | 
				
			||||||
 | 
					            endTimeMs = sunsetMs;
 | 
				
			||||||
 | 
					            scaledStartMs = SCALED_SUNRISE_MS;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // Nighttime
 | 
				
			||||||
 | 
					            if (unixTimestampMs >= sunsetMs) {
 | 
				
			||||||
 | 
					                // After sunset
 | 
				
			||||||
 | 
					                startTimeMs = sunsetMs;
 | 
				
			||||||
 | 
					                endTimeMs = calendar.tomorrow().twilight(coordinates).sunrise().toInstant(ZoneOffset.UTC).toEpochMilli();
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // Before sunrise
 | 
				
			||||||
 | 
					                Twilight yesterdayTwilight = calendar.yesterday().twilight(coordinates);
 | 
				
			||||||
 | 
					                startTimeMs = yesterdayTwilight.sunset().toInstant(ZoneOffset.UTC).toEpochMilli();
 | 
				
			||||||
 | 
					                endTimeMs = sunriseMs;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            scaledStartMs = SCALED_SUNSET_MS;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        double durationMs = endTimeMs - startTimeMs;
 | 
				
			||||||
 | 
					        double progress = (unixTimestampMs - startTimeMs) / durationMs;
 | 
				
			||||||
 | 
					        long scaledOffsetMs = scaledStartMs + (long) (progress * SCALED_DAY_LENGTH_MS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Ensure the result is within the same day (0 to MILLIS_PER_DAY - 1)
 | 
				
			||||||
 | 
					        return scaledOffsetMs % MILLIS_PER_DAY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -7,31 +7,35 @@ import eu.m724.realweather.DebugLogger;
 | 
				
			||||||
import eu.m724.realweather.GlobalConstants;
 | 
					import eu.m724.realweather.GlobalConstants;
 | 
				
			||||||
import eu.m724.realweather.mapper.Mapper;
 | 
					import eu.m724.realweather.mapper.Mapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.LocalTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class TimeMaster {
 | 
					public class TimeMaster {
 | 
				
			||||||
	private TimeConfig timeConfig;
 | 
						private final Mapper mapper = GlobalConstants.getMapper();
 | 
				
			||||||
	private Mapper mapper = GlobalConstants.getMapper();
 | 
						private final Plugin plugin = GlobalConstants.getPlugin();
 | 
				
			||||||
	private Plugin plugin = GlobalConstants.getPlugin();
 | 
					
 | 
				
			||||||
 | 
						private final TimeConfig timeConfig;
 | 
				
			||||||
 | 
						private final TimeConverter timeConverter;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	public TimeMaster(TimeConfig timeConfig) {
 | 
						public TimeMaster(TimeConfig timeConfig) {
 | 
				
			||||||
		this.timeConfig = timeConfig;
 | 
							this.timeConfig = timeConfig;
 | 
				
			||||||
 | 
							this.timeConverter = new TimeConverter(timeConfig.scale());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	public void init() {
 | 
						public void init() {
 | 
				
			||||||
		if (!timeConfig.enabled)
 | 
							if (!timeConfig.enabled())
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		long period = (long) (72 / timeConfig.scale);
 | 
							long period = timeConverter.calculateUpdatePeriod();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (timeConfig.scale * Math.floor(period) != 72.0) {
 | 
							if (timeConfig.scale() * period != 72.0) {
 | 
				
			||||||
			// TODO log this properly
 | 
								// TODO log this properly
 | 
				
			||||||
			DebugLogger.info("Warning: RealTime scale is not optimal. Time will be out of sync.", 0);
 | 
								DebugLogger.info("Warning: RealTime scale is not optimal. Time will be out of sync.", 0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		new SyncTimeUpdateTask(timeConfig).runTaskTimer(plugin, 0, period);
 | 
							new SyncTimeUpdateTask(timeConverter, timeConfig).runTaskTimer(plugin, 0, period);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (timeConfig.dynamic)
 | 
							if (timeConfig.dynamic())
 | 
				
			||||||
			new AsyncPlayerTimeTask(timeConfig).runTaskTimerAsynchronously(plugin, 0, period);
 | 
								new AsyncPlayerTimeTask(timeConverter, timeConfig).runTaskTimerAsynchronously(plugin, 0, period);
 | 
				
			||||||
			// TODO maybe use a different period?
 | 
								// TODO maybe use a different period?
 | 
				
			||||||
			// TODO also make it on player join
 | 
								// TODO also make it on player join
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,5 +22,4 @@ twilight: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# x in game day cycles in 1 irl day cycle
 | 
					# x in game day cycles in 1 irl day cycle
 | 
				
			||||||
# Time will no longer be in sync
 | 
					# Time will no longer be in sync
 | 
				
			||||||
# Can be decimal
 | 
					 | 
				
			||||||
scale: 1.0
 | 
					scale: 1.0
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/test/java/TimeConverterTest.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/test/java/TimeConverterTest.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					import eu.m724.realweather.time.TimeConverter;
 | 
				
			||||||
 | 
					import eu.m724.wtapi.object.Coordinates;
 | 
				
			||||||
 | 
					import eu.m724.wtapi.object.Twilight;
 | 
				
			||||||
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.time.LocalDateTime;
 | 
				
			||||||
 | 
					import java.time.ZoneOffset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TimeConverterTest {
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void testTimeConverter() {
 | 
				
			||||||
 | 
					        TimeConverter timeConverter = new TimeConverter(2.0);
 | 
				
			||||||
 | 
					        System.out.println("Scale: " + timeConverter.scale);
 | 
				
			||||||
 | 
					        long time = LocalDateTime.now().withHour(12).toInstant(ZoneOffset.UTC).toEpochMilli();
 | 
				
			||||||
 | 
					        System.out.println("Time: " + LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC));
 | 
				
			||||||
 | 
					        time = timeConverter.scale(time);
 | 
				
			||||||
 | 
					        System.out.println("Time scaled: " + LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC));
 | 
				
			||||||
 | 
					        System.out.println("Those times are UTC so add 7 hours");
 | 
				
			||||||
 | 
					        time = timeConverter.offsetTwilight(time, new Coordinates(42, 69)); // TODO change numbers before committing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        time = timeConverter.millisToTicks(time);
 | 
				
			||||||
 | 
					        System.out.println("Day ticks: " + time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        System.out.println();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        System.out.println("Scale: " + timeConverter.scale);
 | 
				
			||||||
 | 
					        time = LocalDateTime.now().withHour(12).toInstant(ZoneOffset.UTC).toEpochMilli();
 | 
				
			||||||
 | 
					        System.out.println("Time: " + LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC));
 | 
				
			||||||
 | 
					        time = timeConverter.scale(time);
 | 
				
			||||||
 | 
					        System.out.println("Time scaled: " + LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC));
 | 
				
			||||||
 | 
					        System.out.println("Those times are UTC so add 7 hours");
 | 
				
			||||||
 | 
					        time = timeConverter.offsetTwilight(time, new Coordinates(70, 0)); // TODO change numbers before committing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        time = timeConverter.millisToTicks(time);
 | 
				
			||||||
 | 
					        System.out.println("Day ticks: " + time);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue