add relative time

This commit is contained in:
Sen 2025-08-03 16:45:14 +02:00
parent 83082f4f3c
commit 2f9e7ba728
Signed by: sen
GPG key ID: 3AC50A6F47D1B722
7 changed files with 57 additions and 30 deletions

View file

@ -285,6 +285,7 @@ public class Client implements IThreadListener {
private final class WorldClient extends World { private final class WorldClient extends World {
public WorldClient(Dimension dim) { public WorldClient(Dimension dim) {
super(dim, true); super(dim, true);
this.daytime = dim.getTimeOffset();
this.calculateInitialSkylight(); this.calculateInitialSkylight();
this.calculateInitialWeather(); this.calculateInitialWeather();
this.updatePhysics(); this.updatePhysics();

View file

@ -92,6 +92,7 @@ public abstract class Dimension extends Section {
private long seed = 0L; private long seed = 0L;
private boolean exterminated = false; private boolean exterminated = false;
private long timeExisted = 0L; private long timeExisted = 0L;
private long timeOffset = 0L;
private Weather weather = this.defaultWeather; private Weather weather = this.defaultWeather;
protected Dimension(boolean custom) { protected Dimension(boolean custom) {
@ -113,6 +114,10 @@ public abstract class Dimension extends Section {
this.timeExisted = time; this.timeExisted = time;
} }
public final void setTimeOffset(long time) {
this.timeOffset = time;
}
public final void setCurrentWeather(Weather weather) { public final void setCurrentWeather(Weather weather) {
this.weather = weather; this.weather = weather;
} }
@ -130,6 +135,10 @@ public abstract class Dimension extends Section {
return this.timeExisted; return this.timeExisted;
} }
public final long getTimeOffset() {
return this.timeOffset;
}
public final Weather getCurrentWeather() { public final Weather getCurrentWeather() {
return this.weather; return this.weather;
} }
@ -435,10 +444,11 @@ public abstract class Dimension extends Section {
return dim; return dim;
} }
public final TagObject writeData(boolean send) { public final TagObject writeData(boolean send, long offset) {
TagObject tag = new TagObject(); TagObject tag = new TagObject();
tag.setLong("Seed", this.seed); tag.setLong("Seed", this.seed);
tag.setLong("Time", this.timeExisted); tag.setLong("Time", this.timeExisted);
tag.setLong("Offset", offset);
if(this == Space.INSTANCE) if(this == Space.INSTANCE)
return tag; return tag;
tag.setBool("Exterminated", this.exterminated); tag.setBool("Exterminated", this.exterminated);
@ -452,6 +462,7 @@ public abstract class Dimension extends Section {
public final void readData(TagObject tag) { public final void readData(TagObject tag) {
this.seed = tag.getLong("Seed"); this.seed = tag.getLong("Seed");
this.timeExisted = tag.getLong("Time"); this.timeExisted = tag.getLong("Time");
this.timeOffset = tag.getLong("Offset");
if(this == Space.INSTANCE) if(this == Space.INSTANCE)
return; return;
this.exterminated = tag.getBool("Exterminated"); this.exterminated = tag.getBool("Exterminated");

View file

@ -14,8 +14,8 @@ public class SPacketJoinGame extends SPacketRespawn {
} }
@Serverside @Serverside
public SPacketJoinGame(int id, Dimension dim, String name, int type, boolean editor) { public SPacketJoinGame(int id, Dimension dim, long time, String name, int type, boolean editor) {
super(dim, name, type, editor); super(dim, time, name, type, editor);
this.entityId = id; this.entityId = id;
} }

View file

@ -27,10 +27,10 @@ public class SPacketRespawn implements Packet<IClientPlayer> {
} }
@Serverside @Serverside
public SPacketRespawn(Dimension dim, String name, int type, boolean editor) { public SPacketRespawn(Dimension dim, long time, String name, int type, boolean editor) {
if(dim != null) { if(dim != null) {
this.dimType = dim.getType(); this.dimType = dim.getType();
this.dimData = dim.writeData(true); this.dimData = dim.writeData(true, time);
if(this.dimType == DimType.PLANET || this.dimType == DimType.MOON) { if(this.dimType == DimType.PLANET || this.dimType == DimType.MOON) {
this.sunColor = dim.getSunColor(); this.sunColor = dim.getSunColor();
this.moonColors = dim.getMoonColors(); this.moonColors = dim.getMoonColors();

View file

@ -344,9 +344,8 @@ public final class Server implements IThreadListener, Executor {
tag.setList("Dimensions", list); tag.setList("Dimensions", list);
} }
private void saveServerConfig(long time) { private void saveServerConfig() {
TagObject tag = new TagObject(); TagObject tag = new TagObject();
tag.setLong("Time", time);
tag.setLong("LastAccess", System.currentTimeMillis()); tag.setLong("LastAccess", System.currentTimeMillis());
tag.setString("Version", Util.VERSION); tag.setString("Version", Util.VERSION);
TagObject cfg = new TagObject(); TagObject cfg = new TagObject();
@ -375,7 +374,7 @@ public final class Server implements IThreadListener, Executor {
} }
} }
private long loadServerConfig() { private void loadServerConfig() {
File file = new File("server.cdt"); File file = new File("server.cdt");
if(!file.exists()) if(!file.exists())
file = new File("server.cdt.tmp"); file = new File("server.cdt.tmp");
@ -392,9 +391,7 @@ public final class Server implements IThreadListener, Executor {
long lastPlayed = tag.getLong("LastAccess"); long lastPlayed = tag.getLong("LastAccess");
String version = tag.hasString("Version") ? tag.getString("Version") : null; String version = tag.hasString("Version") ? tag.getString("Version") : null;
version = version != null && version.isEmpty() ? "<unbekannt>" : version; version = version != null && version.isEmpty() ? "<unbekannt>" : version;
long time = tag.hasLong("Time") ? tag.getLong("Time") : World.START_TIME;
Log.IO.info("Config-Version: %s", version); Log.IO.info("Config-Version: %s", version);
Log.IO.info("Weltzeit: %d Ticks / %d Sekunden", time, time / 20L);
Log.IO.info("Zuletzt geladen: %s", new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date(lastPlayed))); Log.IO.info("Zuletzt geladen: %s", new SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(new Date(lastPlayed)));
if(System.getProperty("server.regenkey") == null && tag.hasByteArray("PrivateKey") && tag.hasByteArray("PublicKey")) { if(System.getProperty("server.regenkey") == null && tag.hasByteArray("PrivateKey") && tag.hasByteArray("PublicKey")) {
PrivateKey key = EncryptUtil.decodePrivateKey(tag.getByteArray("PrivateKey")); PrivateKey key = EncryptUtil.decodePrivateKey(tag.getByteArray("PrivateKey"));
@ -402,7 +399,7 @@ public final class Server implements IThreadListener, Executor {
if(key != null && pubkey != null) if(key != null && pubkey != null)
this.keyPair = new KeyPair(pubkey, key); this.keyPair = new KeyPair(pubkey, key);
} }
return time; return;
} }
catch(Exception e) { catch(Exception e) {
Log.IO.error(e, "Fehler beim Lesen von " + file); Log.IO.error(e, "Fehler beim Lesen von " + file);
@ -412,7 +409,6 @@ public final class Server implements IThreadListener, Executor {
} }
} }
Log.IO.info("Erstelle neue Welt und Konfiguration"); Log.IO.info("Erstelle neue Welt und Konfiguration");
return World.START_TIME;
} }
private void loadDimension(Dimension dim) { private void loadDimension(Dimension dim) {
@ -437,7 +433,7 @@ public final class Server implements IThreadListener, Executor {
} }
private void saveDimension(Dimension dim) { private void saveDimension(Dimension dim) {
TagObject tag = dim.writeData(false); TagObject tag = dim.writeData(false, dim == Space.INSTANCE ? this.space.getDayTime() : dim.getTimeOffset());
File file = new File(new File(new File("chunk"), UniverseRegistry.getName(dim)), "data.cdt"); File file = new File(new File(new File("chunk"), UniverseRegistry.getName(dim)), "data.cdt");
try { try {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
@ -598,7 +594,7 @@ public final class Server implements IThreadListener, Executor {
} }
public void saveWorldInfo() { public void saveWorldInfo() {
this.saveServerConfig(this.space.getDayTime()); this.saveServerConfig();
for(Dimension dim : UniverseRegistry.getDimensions()) { for(Dimension dim : UniverseRegistry.getDimensions()) {
this.saveDimension(dim); this.saveDimension(dim);
} }
@ -678,7 +674,7 @@ public final class Server implements IThreadListener, Executor {
public void run(long time) { public void run(long time) {
Region.loadMap(); Region.loadMap();
long wtime = this.loadServerConfig(); this.loadServerConfig();
for(Dimension dim : UniverseRegistry.getDimensions()) { for(Dimension dim : UniverseRegistry.getDimensions()) {
this.loadDimension(dim); this.loadDimension(dim);
} }
@ -688,7 +684,7 @@ public final class Server implements IThreadListener, Executor {
this.keyPair = EncryptUtil.createKeypair(); this.keyPair = EncryptUtil.createKeypair();
} }
User.loadDatabase(this.users); User.loadDatabase(this.users);
this.worlds.add(this.space = new WorldServer(this, wtime, Space.INSTANCE, UniverseRegistry.getGenerator(Space.INSTANCE))); this.worlds.add(this.space = new WorldServer(this, 0L, Space.INSTANCE, UniverseRegistry.getGenerator(Space.INSTANCE)));
this.dimensions.put(UniverseRegistry.getId(this.space.dimension), this.space); this.dimensions.put(UniverseRegistry.getId(this.space.dimension), this.space);
new File("players").mkdirs(); new File("players").mkdirs();
this.setTpsTarget(20.0f); this.setTpsTarget(20.0f);
@ -809,7 +805,7 @@ public final class Server implements IThreadListener, Executor {
} }
if(++this.syncTimer == 20) { if(++this.syncTimer == 20) {
for(Player conn : this.players) { for(Player conn : this.players) {
this.sendPacket(new SPacketTimeUpdate(this.space.getDayTime(), Dimensions.formatTime(conn.getPresentEntity() == null ? this.space : (WorldServer)conn.getPresentEntity().worldObj, conn.getPresentEntity(), true), this.getInfo())); this.sendPacket(new SPacketTimeUpdate((conn.getPresentEntity() == null ? this.space : conn.getPresentEntity().worldObj).getDayTime(), Dimensions.formatTime(conn.getPresentEntity() == null ? this.space : (WorldServer)conn.getPresentEntity().worldObj, conn.getPresentEntity(), true), this.getInfo()));
} }
this.syncTimer = 0; this.syncTimer = 0;
} }
@ -1016,7 +1012,7 @@ public final class Server implements IThreadListener, Executor {
} }
conn.sendPacket(new SPacketServerConfig(vars)); conn.sendPacket(new SPacketServerConfig(vars));
conn.sendPacket(new SPacketDimensions(Dimensions.getDimensionData())); conn.sendPacket(new SPacketDimensions(Dimensions.getDimensionData()));
conn.sendPacket(new SPacketJoinGame(player.getId(), world.dimension, UniverseRegistry.getName(world.dimension), EntityRegistry.getEntityID(player), tag == null)); conn.sendPacket(new SPacketJoinGame(player.getId(), world.dimension, world.getDayTime(), UniverseRegistry.getName(world.dimension), EntityRegistry.getEntityID(player), tag == null));
conn.sendPacket(new SPacketHeldItemChange(player.getSelectedIndex())); conn.sendPacket(new SPacketHeldItemChange(player.getSelectedIndex()));
this.sendPacket(new SPacketPlayerListItem(false, conn)); this.sendPacket(new SPacketPlayerListItem(false, conn));
@ -1151,7 +1147,7 @@ public final class Server implements IThreadListener, Executor {
nplayer.setPosition(nplayer.posX, nplayer.posY + 1.0D, nplayer.posZ); nplayer.setPosition(nplayer.posX, nplayer.posY + 1.0D, nplayer.posZ);
} }
} }
conn.sendPacket(new SPacketRespawn(world.dimension != oldWorld.dimension ? world.dimension : null, world.dimension != oldWorld.dimension ? UniverseRegistry.getName(world.dimension) : null, EntityRegistry.getEntityID(nplayer), conn.isInEditor())); conn.sendPacket(new SPacketRespawn(world.dimension != oldWorld.dimension ? world.dimension : null, world.getDayTime(), world.dimension != oldWorld.dimension ? UniverseRegistry.getName(world.dimension) : null, EntityRegistry.getEntityID(nplayer), conn.isInEditor()));
conn.setPlayerLocation(nplayer.posX, nplayer.posY, nplayer.posZ, nplayer.rotYaw, nplayer.rotPitch); conn.setPlayerLocation(nplayer.posX, nplayer.posY, nplayer.posZ, nplayer.rotYaw, nplayer.rotPitch);
conn.sendPacket(new SPacketSetExperience(nplayer.experience, nplayer.experienceTotal, nplayer.experienceLevel)); conn.sendPacket(new SPacketSetExperience(nplayer.experience, nplayer.experienceTotal, nplayer.experienceLevel));
this.updateTimeAndWeatherForPlayer(conn, world); this.updateTimeAndWeatherForPlayer(conn, world);
@ -1193,7 +1189,7 @@ public final class Server implements IThreadListener, Executor {
world.loadChunk((int)nplayer.posX >> 4, (int)nplayer.posZ >> 4); world.loadChunk((int)nplayer.posX >> 4, (int)nplayer.posZ >> 4);
world.addPlayer(nplayer); world.addPlayer(nplayer);
world.spawnEntityInWorld(nplayer); world.spawnEntityInWorld(nplayer);
conn.sendPacket(new SPacketRespawn(world.dimension != oldWorld.dimension ? world.dimension : null, world.dimension != oldWorld.dimension ? UniverseRegistry.getName(world.dimension) : null, EntityRegistry.getEntityID(nplayer), conn.isInEditor())); conn.sendPacket(new SPacketRespawn(world.dimension != oldWorld.dimension ? world.dimension : null, world.getDayTime(), world.dimension != oldWorld.dimension ? UniverseRegistry.getName(world.dimension) : null, EntityRegistry.getEntityID(nplayer), conn.isInEditor()));
conn.sendPacket(new SPacketSkin(nplayer.getId(), nplayer.getSkin())); // , nplayer.getModel())); conn.sendPacket(new SPacketSkin(nplayer.getId(), nplayer.getSkin())); // , nplayer.getModel()));
conn.setPlayerLocation(nplayer.posX, nplayer.posY, nplayer.posZ, nplayer.rotYaw, nplayer.rotPitch); conn.setPlayerLocation(nplayer.posX, nplayer.posY, nplayer.posZ, nplayer.rotYaw, nplayer.rotPitch);
conn.sendPacket(new SPacketSetExperience(nplayer.experience, nplayer.experienceTotal, nplayer.experienceLevel)); conn.sendPacket(new SPacketSetExperience(nplayer.experience, nplayer.experienceTotal, nplayer.experienceLevel));
@ -1211,7 +1207,7 @@ public final class Server implements IThreadListener, Executor {
public void transferToDimension(EntityNPC player, Dimension dimension, BlockPos pos, float yaw, float pitch, PortalType portal) { public void transferToDimension(EntityNPC player, Dimension dimension, BlockPos pos, float yaw, float pitch, PortalType portal) {
WorldServer oldWorld = (WorldServer)player.getServerWorld(); // this.getWorld(player.dimension); WorldServer oldWorld = (WorldServer)player.getServerWorld(); // this.getWorld(player.dimension);
WorldServer newWorld = this.getWorld(dimension); WorldServer newWorld = this.getWorld(dimension);
player.connection.sendPacket(new SPacketRespawn(newWorld.dimension, UniverseRegistry.getName(newWorld.dimension), EntityRegistry.getEntityID(player), player.connection.isInEditor())); player.connection.sendPacket(new SPacketRespawn(newWorld.dimension, newWorld.getDayTime(), UniverseRegistry.getName(newWorld.dimension), EntityRegistry.getEntityID(player), player.connection.isInEditor()));
oldWorld.removePlayerEntityDangerously(player); oldWorld.removePlayerEntityDangerously(player);
player.dead = false; player.dead = false;
this.placeInDimension(player, oldWorld, newWorld, pos, portal); this.placeInDimension(player, oldWorld, newWorld, pos, portal);

View file

@ -1,12 +1,13 @@
package server.command.commands; package server.command.commands;
import common.dimension.Dimension; import common.dimension.Dimension;
import common.util.Position; import common.dimension.Space;
import server.command.Command; import server.command.Command;
import server.command.CommandEnvironment; import server.command.CommandEnvironment;
import server.command.Executor; import server.command.Executor;
import server.command.RunException; import server.command.RunException;
import server.dimension.Dimensions; import server.dimension.Dimensions;
import server.init.UniverseRegistry;
import server.network.Player; import server.network.Player;
import server.world.WorldServer; import server.world.WorldServer;
@ -15,9 +16,11 @@ public class CommandTime extends Command {
super("time"); super("time");
this.addString("time", false, "day", "night", "noon", "midnight", "sunrise", "sunset"); this.addString("time", false, "day", "night", "noon", "midnight", "sunrise", "sunset");
this.addWorld("dim", true);
this.setParamsOptional(); this.setParamsOptional();
this.addFlag("absolute", 'a'); this.addFlag("absolute", 'a');
this.addFlag("global", 'g');
} }
private long parseInt(String input, long max) { private long parseInt(String input, long max) {
@ -69,9 +72,7 @@ public class CommandTime extends Command {
return t * this.parseInt(arg, Long.MAX_VALUE); return t * this.parseInt(arg, Long.MAX_VALUE);
} }
public Object exec(CommandEnvironment env, Executor exec, String timeStr, boolean absolute) { public Object exec(CommandEnvironment env, Executor exec, String timeStr, WorldServer world, boolean absolute, boolean global) {
Position pos = exec.getExecPos();
WorldServer world = pos == null ? env.getServer().getSpace() : env.getServer().getWorld(pos.getDimension());
long time = absolute ? 0L : world.getDayTime(); long time = absolute ? 0L : world.getDayTime();
long fwd = parseDayTime(world.dimension, timeStr); long fwd = parseDayTime(world.dimension, timeStr);
if(fwd >= 0L) { if(fwd >= 0L) {
@ -87,11 +88,29 @@ public class CommandTime extends Command {
else { else {
time += parseTime(world.dimension, timeStr); time += parseTime(world.dimension, timeStr);
} }
for(WorldServer dim : env.getServer().getWorlds()) { if(global) {
dim.setDayTime(time); for(Dimension dim : UniverseRegistry.getDimensions()) {
dim.resetWeather(); dim.setTimeOffset(dim != Space.INSTANCE ? 0L : time);
}
for(WorldServer wld : env.getServer().getWorlds()) {
wld.setDayTime(time);
wld.resetWeather();
}
} }
exec.log("Zeit auf %s gesetzt", Dimensions.formatTime(world, exec.isPlayer() ? ((Player)exec).getPresentEntity() : null, false)); else {
if(world.dimension == Space.INSTANCE) {
long diff = time - world.getDayTime();
for(Dimension dim : UniverseRegistry.getDimensions()) {
dim.setTimeOffset(dim != Space.INSTANCE ? dim.getTimeOffset() - diff : time);
}
}
else {
world.dimension.setTimeOffset(time - env.getServer().getSpace().getDayTime());
}
world.setDayTime(time);
world.resetWeather();
}
exec.log("Zeit " + (global ? "aller Dimensionen (relativ zu %s)" : "in %s") + " auf %s gesetzt", world.dimension.getDisplay(), Dimensions.formatTime(world, exec.isPlayer() ? ((Player)exec).getPresentEntity() : null, false));
return time; return time;
} }
} }

View file

@ -253,7 +253,7 @@ public final class WorldServer extends AWorldServer {
super(dim); super(dim);
this.server = server; this.server = server;
// this.time = time; // this.time = time;
this.daytime = dtime; this.daytime = dtime + this.dimension.getTimeOffset();
this.gen = gen; this.gen = gen;
this.updateViewRadius(); this.updateViewRadius();
this.chunkDir = new File(new File("chunk"), UniverseRegistry.getName(dim)); this.chunkDir = new File(new File("chunk"), UniverseRegistry.getName(dim));