Skip to content

Commit 7e1af33

Browse files
committed
Fix per-player time
1 parent 86c93c5 commit 7e1af33

12 files changed

Lines changed: 69 additions & 73 deletions

File tree

paper-api/src/main/java/org/bukkit/World.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,10 +2094,8 @@ default boolean setSpawnLocation(int x, int y, int z) {
20942094
*
20952095
* @param time The new absolute time to set this world to
20962096
* @see #setTime(long) Sets the relative time of this world
2097-
* @deprecated all overworlds share the same world clock by default now
20982097
* @throws IllegalArgumentException if this world does not have a world clock (e.g. the nether)
20992098
*/
2100-
@Deprecated // TODO world clock API with links to it
21012099
public void setFullTime(long time);
21022100

21032101
// Paper start

paper-api/src/main/java/org/bukkit/event/world/ClockTimeSkipEvent.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* If the event is cancelled the time will not change.
1313
*/
1414
// TODO - snapshot - 26.1 clock
15+
@ApiStatus.Experimental
1516
public class ClockTimeSkipEvent extends Event implements Cancellable {
1617

1718
private static final HandlerList HANDLER_LIST = new HandlerList();

paper-api/src/main/java/org/bukkit/event/world/TimeSkipEvent.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* Called when the time skips in a world.
1010
* <p>
1111
* If the event is cancelled the time will not change.
12+
*
13+
* @see ClockTimeSkipEvent for changing of clocks that affect all worlds
1214
*/
1315
public class TimeSkipEvent extends ClockTimeSkipEvent {
1416

paper-server/patches/features/0001-Moonrise-optimisation-patches.patch

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23838,7 +23838,7 @@ index 3c1490ac7c259da04031db2f170e0c0a5f512191..470d7c770ae9d045b97e2df145cfe3cf
2383823838
}
2383923839
}
2384023840
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
23841-
index c11e2ce21e43f677bfccb65e6b5ad374912381fa..9aae782f8f9f1c0f7eae394ec0a1bda79e93f6f4 100644
23841+
index e5925d778c28bd19ee4cb911fb115edc6351c26b..b4d7ccc2fd9e6c928445b09dbc6ac896c81fc2ef 100644
2384223842
--- a/net/minecraft/server/MinecraftServer.java
2384323843
+++ b/net/minecraft/server/MinecraftServer.java
2384423844
@@ -191,7 +191,7 @@ import net.minecraft.world.scores.ScoreboardSaveData;
@@ -24079,7 +24079,7 @@ index c11e2ce21e43f677bfccb65e6b5ad374912381fa..9aae782f8f9f1c0f7eae394ec0a1bda7
2407924079
this.tickFrame.end();
2408024080
this.recordEndOfTick(); // Paper - improve tick loop
2408124081
profiler.pop();
24082-
@@ -2610,6 +2729,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
24082+
@@ -2600,6 +2719,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
2408324083
}
2408424084
}
2408524085

@@ -28487,11 +28487,11 @@ index 83af9ee3ba150da85b9b694cd76a5fabb5b2d8ef..1fb40837bd02672850ec9adc2797190d
2848728487
PrepareSpawnTask.this.loadListener.updateFocus(this.spawnLevel.dimension(), spawnChunk);
2848828488
}
2848928489
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
28490-
index c4f8f0e1013809260977c0874205fbaeebb27e95..b928b58ea5f0b4268b999ce4a23fe2fbc3042f4e 100644
28490+
index 0c4de29676732f5e84d7584e1f89d508addc1cc4..0613b053f4a75c0884280011ee092d9d108b3857 100644
2849128491
--- a/net/minecraft/server/players/PlayerList.java
2849228492
+++ b/net/minecraft/server/players/PlayerList.java
28493-
@@ -982,8 +982,8 @@ public abstract class PlayerList {
28494-
player.connection.send(this.server.clockManager().createFullSyncPacket());
28493+
@@ -983,8 +983,8 @@ public abstract class PlayerList {
28494+
player.connection.send(level.clockManager().createFullSyncPacket(player)); // Paper - per-world time; per-player time
2849528495
player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getRespawnData()));
2849628496
// Paper start - view distances
2849728497
- player.connection.send(new ClientboundSetChunkCacheRadiusPacket(io.papermc.paper.FeatureHooks.getViewDistance(level)));

paper-server/patches/features/0016-Add-Alternate-Current-redstone-implementation.patch

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2326,18 +2326,18 @@ index 0000000000000000000000000000000000000000..298076a0db4e6ee6e4775ac43bf749d9
23262326
+ }
23272327
+}
23282328
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
2329-
index 3741607fa3ba755b3a9983ced08460053b75e17f..5a911cc98faeb2db6eaf0d48cc5ff3c1f68f0a84 100644
2329+
index f1341c78e90e0f7d6d2b27e6fff57bf6999f7176..12e6162e82dd639ac34da6466fc201623f4682c5 100644
23302330
--- a/net/minecraft/server/level/ServerLevel.java
23312331
+++ b/net/minecraft/server/level/ServerLevel.java
23322332
@@ -233,6 +233,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
2333-
private ServerClockManager clockManager;
2333+
private @Nullable ServerClockManager clockManager;
23342334
public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
23352335
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
23362336
+ private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
23372337

23382338
@Override
23392339
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
2340-
@@ -2773,6 +2774,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
2340+
@@ -2772,6 +2773,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
23412341
return this.debugSynchronizers;
23422342
}
23432343

paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,7 @@
10961096
ObjectArrayList<NameAndId> sample = new ObjectArrayList<>(sampleSize);
10971097
int offset = Mth.nextInt(this.random, 0, players.size() - sampleSize);
10981098

1099-
@@ -1104,25 +_,73 @@
1099+
@@ -1104,12 +_,46 @@
11001100
protected void tickChildren(final BooleanSupplier haveTime) {
11011101
ProfilerFiller profiler = Profiler.get();
11021102
this.getPlayerList().getPlayers().forEach(playerx -> playerx.connection.suspendFlushing());
@@ -1144,23 +1144,16 @@
11441144
profiler.pop();
11451145
}
11461146

1147-
if (this.tickCount % 20 == 0) {
1148-
profiler.push("timeSync");
1149-
- this.forceGameTimeSynchronization();
1150-
+ // Paper start - per-world game time
1151-
+ for (final ServerLevel level : this.getAllLevels()) {
1152-
+ this.playerList.broadcastAll(new ClientboundSetTimePacket(level.getGameTime(), Map.of()), level);
1153-
+ }
1154-
+ // Paper end - per-world game time
1147+
@@ -1119,10 +_,20 @@
11551148
profiler.pop();
1156-
+ }
1157-
+
1149+
}
1150+
11581151
+ // CraftBukkit start
11591152
+ // Run tasks that are waiting on processing
11601153
+ while (!this.processQueue.isEmpty()) {
11611154
+ this.processQueue.remove().run();
1162-
}
1163-
1155+
+ }
1156+
+
11641157
profiler.push("levels");
11651158
this.updateEffectiveRespawnData();
11661159

@@ -1197,14 +1190,16 @@
11971190
this.effectiveRespawnData = respawnLevel.getWorldBorderAdjustedRespawnData(respawnData);
11981191
}
11991192

1200-
@@ -1179,7 +_,9 @@
1193+
@@ -1179,7 +_,11 @@
12011194
public void forceGameTimeSynchronization() {
12021195
ProfilerFiller profiler = Profiler.get();
12031196
profiler.push("timeSync");
12041197
- this.playerList.broadcastAll(new ClientboundSetTimePacket(this.overworld().getGameTime(), Map.of()));
1198+
+ // Paper start - per-world time
12051199
+ for (ServerLevel level : this.getAllLevels()) {
12061200
+ this.playerList.broadcastAll(new ClientboundSetTimePacket(level.getGameTime(), Map.of()), level);
12071201
+ }
1202+
+ // Paper end - per-world time
12081203
profiler.pop();
12091204
}
12101205

@@ -1591,7 +1586,7 @@
15911586
+ level.setSpawnSettings(level.isSpawningMonsters()); // Paper - per-world game rules
15921587
} else if (rule == GameRules.ADVANCE_TIME) {
15931588
- this.getPlayerList().broadcastAll(this.clockManager().createFullSyncPacket());
1594-
+ this.getPlayerList().broadcastAll(level.clockManager().createFullSyncPacket(), level); // Paper - per-world time
1589+
+ level.players().forEach(player -> player.connection.send(level.clockManager().createFullSyncPacket(player))); // Paper - per-world time; per-player time
15951590
}
15961591
}
15971592

paper-server/patches/sources/net/minecraft/server/commands/TimeCommand.java.patch

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
long currentTicks = timeline.value().getCurrentTicks(clockManager);
2828
source.sendSuccess(() -> Component.translatable("commands.time.query.timeline", timeline.getRegisteredName(), currentTicks), false);
2929
return wrapTime(currentTicks);
30-
@@ -162,33 +_,47 @@
30+
@@ -162,33 +_,53 @@
3131
if (!clock.equals(timeline.value().clock())) {
3232
throw ERROR_WRONG_TIMELINE_FOR_CLOCK.create(clock.getRegisteredName(), timeline.getRegisteredName());
3333
} else {
@@ -43,14 +43,20 @@
4343
private static int setTotalTicks(final CommandSourceStack source, final Holder<WorldClock> clock, final int totalTicks) {
4444
- ServerClockManager clockManager = source.getServer().clockManager();
4545
- clockManager.setTotalTicks(clock, totalTicks);
46+
- source.sendSuccess(() -> Component.translatable("commands.time.set.absolute", clock.getRegisteredName(), totalTicks), true);
47+
- return totalTicks;
4648
+ ServerClockManager clockManager = source.getLevel().clockManager();
4749
+ long currentTotalTicks = clockManager.getTotalTicks(clock);
4850
+ org.bukkit.event.world.ClockTimeSkipEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callTimeSkipEvent(source, totalTicks - currentTotalTicks);
51+
+ final long newTotalTicks;
4952
+ if (event.callEvent()) {
50-
+ clockManager.setTotalTicks(clock, currentTotalTicks + event.getSkipAmount());
53+
+ newTotalTicks = currentTotalTicks + event.getSkipAmount();
54+
+ clockManager.setTotalTicks(clock, newTotalTicks);
55+
+ } else {
56+
+ newTotalTicks = totalTicks; // just pass it through
5157
+ }
52-
source.sendSuccess(() -> Component.translatable("commands.time.set.absolute", clock.getRegisteredName(), totalTicks), true);
53-
return totalTicks;
58+
+ source.sendSuccess(() -> Component.translatable("commands.time.set.absolute", clock.getRegisteredName(), newTotalTicks), true);
59+
+ return wrapTime(newTotalTicks);
5460
}
5561

5662
private static int addTime(final CommandSourceStack source, final Holder<WorldClock> clock, final int time) {
@@ -69,6 +75,7 @@
6975
private static int setTimeToTimeMarker(final CommandSourceStack source, final Holder<WorldClock> clock, final ResourceKey<ClockTimeMarker> timeMarkerId) throws CommandSyntaxException {
7076
- ServerClockManager clockManager = source.getServer().clockManager();
7177
- if (!clockManager.moveToTimeMarker(clock, timeMarkerId)) {
78+
+ // Paper start - per-world time
7279
+ ServerClockManager clockManager = source.getLevel().clockManager();
7380
+ java.util.OptionalLong targetTime = clockManager.getTotalTicksToTimeMarker(clock, timeMarkerId);
7481
+ if (targetTime.isEmpty()) {
@@ -79,26 +86,23 @@
7986
+ if (event.callEvent()) {
8087
+ clockManager.setTotalTicks(clock, currentTime + event.getSkipAmount());
8188
+ }
89+
+ // Paper end - per-world time
8290
source.sendSuccess(
8391
() -> Component.translatable("commands.time.set.time_marker", clock.getRegisteredName(), timeMarkerId.identifier().toString()), true
8492
);
85-
@@ -197,16 +_,17 @@
93+
@@ -197,13 +_,13 @@
8694
}
8795

8896
private static int setPaused(final CommandSourceStack source, final Holder<WorldClock> clock, final boolean paused) {
8997
- source.getServer().clockManager().setPaused(clock, paused);
90-
+ source.getLevel().clockManager().setPaused(clock, paused);
98+
+ source.getLevel().clockManager().setPaused(clock, paused); // Paper - per-world time
9199
source.sendSuccess(() -> Component.translatable(paused ? "commands.time.pause" : "commands.time.resume", clock.getRegisteredName()), true);
92100
return 1;
93101
}
94102

95103
private static int setRate(final CommandSourceStack source, final Holder<WorldClock> clock, final float rate) {
96104
- source.getServer().clockManager().setRate(clock, rate);
97-
+ source.getLevel().clockManager().setRate(clock, rate);
105+
+ source.getLevel().clockManager().setRate(clock, rate); // Paper - per-world time
98106
source.sendSuccess(() -> Component.translatable("commands.time.rate", clock.getRegisteredName(), rate), true);
99107
return 1;
100108
}
101-
+ // Paper end - per-world time
102-
103-
private static int wrapTime(final long ticks) {
104-
return Math.toIntExact(ticks % 2147483647L);

paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
+ private final WeatherData weatherData;
2323
+ public final net.minecraft.world.level.timers.TimerQueue<net.minecraft.server.MinecraftServer> scheduledEvents;
2424
+ public final WorldGenSettings worldGenSettings;
25-
+ private ServerClockManager clockManager;
25+
+ private @Nullable ServerClockManager clockManager;
2626
+ public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
2727
+ public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
2828
+

paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@
745745
WorldBorder worldBorder = level.getWorldBorder();
746746
player.connection.send(new ClientboundInitializeBorderPacket(worldBorder));
747747
- player.connection.send(this.server.clockManager().createFullSyncPacket());
748-
+ player.connection.send(level.clockManager().createFullSyncPacket()); // Paper - per-world time
748+
+ player.connection.send(level.clockManager().createFullSyncPacket(player)); // Paper - per-world time; per-player time
749749
player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getRespawnData()));
750750
+ // Paper start - view distances
751751
+ player.connection.send(new ClientboundSetChunkCacheRadiusPacket(io.papermc.paper.FeatureHooks.getViewDistance(level)));

paper-server/patches/sources/net/minecraft/world/clock/ServerClockManager.java.patch

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,20 @@
6969
}
7070

7171
@Override
72-
@@ -127,12 +_,40 @@
72+
@@ -127,12 +_,48 @@
7373
}
7474

7575
public ClientboundSetTimePacket createFullSyncPacket() {
7676
- return new ClientboundSetTimePacket(this.getGameTime(), Util.mapValues(this.clocks, clock -> clock.packNetworkState(this.server)));
77-
+ return new ClientboundSetTimePacket(this.getGameTime(), Util.mapValues(this.clocks, clock -> clock.packNetworkState(this.advanceTime()))); // Paper - per-world time
77+
+ // Paper start - per-player time
78+
+ return this.createFullSyncPacket(null);
79+
+ }
80+
+
81+
+ public ClientboundSetTimePacket createFullSyncPacket(final net.minecraft.server.level.ServerPlayer player) {
82+
+ final Map<Holder<WorldClock>, ClockNetworkState> updates = new HashMap<>(this.clocks.size());
83+
+ this.clocks.forEach((clock, instance) -> updates.put(clock, this.packNetworkState(clock, instance, player)));
84+
+ return new ClientboundSetTimePacket(this.getGameTime(), updates);
85+
+ // Paper end - per-player time
7886
}
7987

8088
private long getGameTime() {
@@ -83,33 +91,33 @@
8391
+ return this.level != null ? this.level.getGameTime() : this.server.overworld().getGameTime(); // Paper - per-world time
8492
+ }
8593
+
86-
+ // Paper start - per-world time
87-
+ // TODO - snapshot: just make the inner class, fields and getter public
88-
+ public boolean isPaused(final Holder<WorldClock> definition) {
89-
+ return this.getInstance(definition).paused;
90-
+ }
91-
+
92-
+ public float partialTick(final Holder<WorldClock> definition) {
93-
+ return this.getInstance(definition).partialTick;
94-
+ }
95-
+
96-
+ public float rate(final Holder<WorldClock> definition) {
97-
+ return this.getInstance(definition).rate;
94+
+ // Paper start - per-world time; per-player time
95+
+ private void broadcastUpdates(final Holder<WorldClock> clock, final ServerClockManager.ClockInstance instance) {
96+
+ for (final net.minecraft.server.level.ServerPlayer player : this.level != null ? this.level.players() : this.server.getPlayerList().getPlayers()) {
97+
+ final var packet = new net.minecraft.network.protocol.game.ClientboundSetTimePacket(
98+
+ this.getGameTime(),
99+
+ java.util.Map.of(clock, this.packNetworkState(clock, instance, player))
100+
+ );
101+
+ player.connection.send(packet);
102+
+ }
98103
+ }
99104
+
100-
+ private void broadcastUpdates(final Holder<WorldClock> clock, final ServerClockManager.ClockInstance instance) {
101-
+ final ClientboundSetTimePacket packet = new ClientboundSetTimePacket(this.getGameTime(), Map.of(clock, instance.packNetworkState(this.advanceTime())));
102-
+ if (this.level != null) {
103-
+ this.server.getPlayerList().broadcastAll(packet, this.level);
104-
+ } else {
105-
+ this.server.getPlayerList().broadcastAll(packet);
105+
+ private ClockNetworkState packNetworkState(
106+
+ final Holder<WorldClock> clock,
107+
+ final ServerClockManager.ClockInstance instance,
108+
+ final net.minecraft.server.level.ServerPlayer player
109+
+ ) {
110+
+ if (player != null && player.level().dimensionType().defaultClock().filter(clock::equals).isPresent()) {
111+
+ final boolean paused = !player.relativeTime || instance.paused || !this.advanceTime();
112+
+ return new ClockNetworkState(player.getPlayerTime(), instance.partialTick, paused ? 0.0F : instance.rate);
106113
+ }
114+
+ return instance.packNetworkState(this.advanceTime());
107115
+ }
108116
+
109117
+ private boolean advanceTime() {
110118
+ return this.level != null ? this.level.getGameRules().get(GameRules.ADVANCE_TIME) : this.server.getGlobalGameRules().get(GameRules.ADVANCE_TIME);
111119
+ }
112-
+ // Paper end - per-world time
120+
+ // Paper end - per-world time; per-player time
113121

114122
public boolean isAtTimeMarker(final Holder<WorldClock> clock, final ResourceKey<ClockTimeMarker> timeMarkerId) {
115123
ServerClockManager.ClockInstance clockInstance = this.getInstance(clock);

0 commit comments

Comments
 (0)