Skip to content
This repository has been archived by the owner on Jun 22, 2024. It is now read-only.

Commit

Permalink
0.5.0 rc
Browse files Browse the repository at this point in the history
this commit implements local real time,
fixes the time formula,
adds logging,
and more refactoring
  • Loading branch information
Minecon724 committed Jan 20, 2024
1 parent ab6df79 commit 59cfca2
Show file tree
Hide file tree
Showing 16 changed files with 231 additions and 127 deletions.
13 changes: 10 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
Milestone: yesterday
- fix bugs

Milestone: 0.5.1
- local maxmind
- account for real sun movement, not just time
- readd metrics
- fix realtime
- cache cleaning
- prevent packets

Milestone: 0.6.0
- account for real sun movement, not just time

Milestone: future
- weather simulator (weather is clientside rn and doesnt have things such as lightning or other effects)
- tests
16 changes: 0 additions & 16 deletions src/main/java/pl/minecon724/realweather/ConfigUtils.java

This file was deleted.

2 changes: 2 additions & 0 deletions src/main/java/pl/minecon724/realweather/RW.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public void onEnable() {
saveDefaultConfig();
config = getConfig();

SubLogger.init(getLogger());

WorldMap.init(
config.getConfigurationSection("map")
);
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/pl/minecon724/realweather/SubLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package pl.minecon724.realweather;

import java.util.logging.Level;
import java.util.logging.Logger;

public class SubLogger {
private static Logger logger;
private String name;

static void init(Logger loger) {
logger = loger;
}

public SubLogger(String name) {
this.name = name;
}

public void log(Level level, String format, Object... args) {
Object[] combinedArgs = new Object[args.length + 1];
combinedArgs[0] = name;
System.arraycopy(args, 0, combinedArgs, 1, args.length);

logger.log(level, String.format("[%s] " + format, combinedArgs));
}

public void info(String format, Object... args) {
this.log(Level.INFO, format, args);
}
}
2 changes: 1 addition & 1 deletion src/main/java/pl/minecon724/realweather/map/WorldMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static void init(ConfigurationSection config)
Type type;

try {
type = Type.valueOf(config.getString("type"));
type = Type.valueOf(config.getString("type").toUpperCase());
} catch (NullPointerException e) {
throw new IllegalArgumentException("Invalid type");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package pl.minecon724.realweather.map.exceptions;

public class GeoIPException extends Exception {

public GeoIPException(String string) {
super(string);
public GeoIPException(String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
package pl.minecon724.realweather.realtime;

import java.util.List;
import java.util.logging.Logger;

import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;

import pl.minecon724.realweather.SubLogger;
import pl.minecon724.realweather.map.Coordinates;
import pl.minecon724.realweather.map.WorldMap;
import pl.minecon724.realweather.map.exceptions.GeoIPException;

public class PlayerTimeSyncTask extends BukkitRunnable {
private WorldMap worldMap = WorldMap.getInstance();
private Logger logger = Logger.getLogger("timezone sync");
private SubLogger subLogger = new SubLogger("playertime");

private double scale;
private List<World> worlds;

public PlayerTimeSyncTask(List<World> worlds) {
public PlayerTimeSyncTask(double scale, List<World> worlds) {
this.scale = scale;
this.worlds = worlds;
}

@Override
public void run() {
for (Player player : Bukkit.getOnlinePlayers()) {
if (!worlds.contains(player.getWorld())) {
subLogger.info("resetting %s's time as they're in an excluded world", player.getName());
player.resetPlayerTime();
continue;
}
Expand All @@ -35,21 +38,37 @@ public void run() {
try {
coordinates = worldMap.getCoordinates(player);
} catch (GeoIPException e) {
logger.warning(
String.format("Unable to determine GeoIP for %s (%s)",
player.getAddress().getHostString()));
subLogger.info("Unable to determine GeoIP for %s (%s)",
player.getAddress().getHostString(), e.getMessage());

continue;
}

// longitude
// / 15 as 15 degrees is 1 hour
// * 60 to minutes
// * 60 again to seconds
// * 20 to ticks
long offset = (long) (coordinates.longitude / 15 * 72000);
/*
* reasoning here:
* earth is divided into timezones each covering 15 deg longitude
* so first we find how many hours to offset
* a day is 24h (no way)
* in minecraft its 24000 ticks
* so, 1h in ticks: 24000t / 24h = 1000t
* seconds in day: 24h * 3600s = 86400s
* seconds to ticks: 86400s * 20t = 1728000t
* day irl is 1728000t, in minecraft its 24000t
* for each minecraft tick, ticks irl: 1728000t / 24000t = 72t
* we divide offset by that to sync time
* then multiply by scale, thats obvious
*/

player.setPlayerTime(offset, true);
double offset = coordinates.longitude / 15;
offset *= 1000;
offset *= scale;

// why no modulo? because we also modify day

long time = (long) offset;

player.setPlayerTime(time, true);
subLogger.info("%s's time is now off by %d ticks", player.getName(), time);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package pl.minecon724.realweather.realtime;

import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bukkit.GameRule;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.EventHandler;
Expand All @@ -14,17 +18,18 @@
import pl.minecon724.realweather.weather.exceptions.DisabledException;

public class RealTimeCommander implements Listener {
RW plugin;
private RW plugin;

List<String> worldNames;
double scale;
ZoneId timezone;
boolean perPlayer;
private List<String> worldNames;
private double scale;
private ZoneId timezone;
private boolean perPlayer;

volatile List<World> worlds;
private volatile List<World> worlds = new ArrayList<>();
private Map<World, Boolean> savedGamerule = new HashMap<>();

RealTimeTask task;
PlayerTimeSyncTask playerTimeSyncTask;
private RealTimeTask task;
private PlayerTimeSyncTask playerTimeSyncTask;

public RealTimeCommander(RW plugin) {
this.plugin = plugin;
Expand All @@ -50,27 +55,38 @@ public void init(ConfigurationSection config)
}

public void start() {
task = new RealTimeTask(scale, timezone, worlds);
// to save processing, run only when necessary
long period = (long) Math.ceil(72 / scale);
period = Math.max(period, 1);

task.runTaskTimer(plugin, 0, 1);
task = new RealTimeTask(scale, timezone, worlds);
task.runTaskTimer(plugin, 0, period);

if (perPlayer) {
playerTimeSyncTask = new PlayerTimeSyncTask(worlds);
playerTimeSyncTask = new PlayerTimeSyncTask(scale, worlds);
playerTimeSyncTask.runTaskTimerAsynchronously(plugin, 0, 40);
}
}

@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
World world = event.getWorld();

if (worldNames.contains(world.getName()))
if (worldNames.contains(world.getName())) {
worlds.add(world);

savedGamerule.put(world, world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE));
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
}
}

@EventHandler
public void onWorldUnload(WorldUnloadEvent event) {
World world = event.getWorld();

worlds.remove(world);
if (savedGamerule.containsKey(world)) {
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, savedGamerule.remove(world));
}
}
}
36 changes: 20 additions & 16 deletions src/main/java/pl/minecon724/realweather/realtime/RealTimeTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,37 @@
import org.bukkit.World;
import org.bukkit.scheduler.BukkitRunnable;

import pl.minecon724.realweather.SubLogger;

public class RealTimeTask extends BukkitRunnable {
double timeScale;
private SubLogger subLogger = new SubLogger("timer");
double scale;
ZoneId timezone;
List<World> worlds;

public RealTimeTask(double timeScale, ZoneId timezone, List<World> worlds) {
this.timeScale = timeScale;
public RealTimeTask(double scale, ZoneId timezone, List<World> worlds) {
this.scale = scale;
this.timezone = timezone;
this.worlds = worlds;
}

@Override
public void run() {
long now = ZonedDateTime.now(timezone).toInstant().getEpochSecond();
now *= timeScale;
now %= 86400;

// day irl is 86400 secs
// in game, its 1200 secs
// to align, 86400 / 1200 = 72
// then we convert to ticks by multiplying 20 (1s = 20t)
// we subtract 24000 - 18000 = 6000 because 18000 is midnight
double time = (now / 72.0) * 20 - 6000;
time %= 24000;
double now = ZonedDateTime.now(timezone).toInstant().getEpochSecond();
now /= 3600; // to hour

// explaination in PlayerTimeSyncTask line 47
now *= 1000; // reallife s to mc ticks
now -= 6000; // 0t is actually 6:00

now *= scale; // scale
now %= 24000;

long time = (long) now;

for (World w : worlds) {
w.setFullTime((long)time);
w.setFullTime(time);
subLogger.info("Updated time for %s (to %d)", w.getName(), time);
}
}
}
}
Loading

0 comments on commit 59cfca2

Please sign in to comment.