Skip to content

Commit 24999d0

Browse files
committed
feat(minecraft): update to 25w37a
Changes: - Changed gamerule tag names - Added NoOpSynchronizer to handle vanished entities See: https://minecraft.wiki/w/Java_Edition_25w37a
1 parent e4c0f7e commit 24999d0

12 files changed

Lines changed: 180 additions & 48 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mixinConfigs=mixins.sponge.accessors.json,mixins.sponge.api.json,mixins.sponge.c
1212
mixins.sponge.tracker.json,mixins.sponge.ipforward.json,mixins.sponge.optimization.json,mixins.sponge.test.json
1313
superClassChanges=common.superclasschange
1414

15-
minecraftVersion=25w36b
15+
minecraftVersion=25w37a
1616
recommendedVersion=0-SNAPSHOT
1717

1818
org.gradle.dependency.verification.console=verbose

src/accessors/java/org/spongepowered/common/accessor/server/level/ChunkMapAccessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public interface ChunkMapAccessor {
4343

4444
@Invoker("saveAllChunks") void invoker$saveAllChunks(boolean flush);
4545

46-
@Invoker("getChunks") Iterable<ChunkHolder> invoker$getChunks();
46+
@Accessor("visibleChunkMap") Long2ObjectLinkedOpenHashMap<ChunkHolder> accessor$visibleChunkMap();
4747

4848
@Accessor("level") ServerLevel accessor$level();
4949
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.common.data.datasync;
26+
27+
import net.minecraft.network.protocol.Packet;
28+
import net.minecraft.network.protocol.game.ClientGamePacketListener;
29+
import net.minecraft.server.level.ServerEntity;
30+
import net.minecraft.server.level.ServerPlayer;
31+
32+
import java.util.function.Predicate;
33+
34+
public record NoOpSynchronizer() implements ServerEntity.Synchronizer {
35+
36+
public static final NoOpSynchronizer INSTANCE = new NoOpSynchronizer();
37+
38+
@Override
39+
public void sendToTrackingPlayers(Packet<? super ClientGamePacketListener> var1) {
40+
41+
}
42+
43+
@Override
44+
public void sendToTrackingPlayersAndSelf(Packet<? super ClientGamePacketListener> var1) {
45+
46+
}
47+
48+
@Override
49+
public void sendToTrackingPlayersFiltered(Packet<? super ClientGamePacketListener> var1, Predicate<ServerPlayer> var2) {
50+
51+
}
52+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.common.data.datasync;
26+
27+
import net.minecraft.network.protocol.Packet;
28+
import net.minecraft.network.protocol.game.ClientGamePacketListener;
29+
import net.minecraft.server.level.ServerEntity;
30+
import net.minecraft.server.level.ServerPlayer;
31+
import net.minecraft.world.entity.Entity;
32+
import org.spongepowered.common.bridge.data.VanishableBridge;
33+
34+
import java.lang.ref.WeakReference;
35+
import java.util.function.Predicate;
36+
37+
public record VanishedFilteringSynchronizer(
38+
ServerEntity.Synchronizer proxy,
39+
WeakReference<Entity> ref
40+
) implements ServerEntity.Synchronizer {
41+
@Override
42+
public void sendToTrackingPlayers(Packet<? super ClientGamePacketListener> var1) {
43+
if (this.ref.get() instanceof VanishableBridge vb) {
44+
if (!vb.bridge$isInvisible()) {
45+
this.proxy.sendToTrackingPlayers(var1);
46+
}
47+
return;
48+
}
49+
this.proxy.sendToTrackingPlayers(var1);
50+
}
51+
52+
@Override
53+
public void sendToTrackingPlayersAndSelf(Packet<? super ClientGamePacketListener> var1) {
54+
if (this.ref.get() instanceof VanishableBridge vb) {
55+
if (!vb.bridge$isInvisible()) {
56+
this.proxy.sendToTrackingPlayersAndSelf(var1);
57+
}
58+
return;
59+
}
60+
this.proxy.sendToTrackingPlayersAndSelf(var1);
61+
}
62+
63+
@Override
64+
public void sendToTrackingPlayersFiltered(Packet<? super ClientGamePacketListener> var1, Predicate<ServerPlayer> var2) {
65+
if (this.ref.get() instanceof VanishableBridge vb) {
66+
if (!vb.bridge$isInvisible()) {
67+
this.proxy.sendToTrackingPlayersFiltered(var1, var2);
68+
}
69+
return;
70+
}
71+
this.proxy.sendToTrackingPlayersFiltered(var1, var2);
72+
}
73+
}

src/main/java/org/spongepowered/common/entity/living/human/HumanEntity.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import org.spongepowered.common.accessor.world.entity.LivingEntityAccessor;
8787
import org.spongepowered.common.accessor.world.entity.player.PlayerAccessor;
8888
import org.spongepowered.common.config.SpongeGameConfigs;
89+
import org.spongepowered.common.data.datasync.NoOpSynchronizer;
8990
import org.spongepowered.common.launch.Launch;
9091
import org.spongepowered.common.profile.SpongeProfileProperty;
9192
import org.spongepowered.common.util.Constants;
@@ -117,7 +118,7 @@ public static AttributeSupplier createAttributes() {
117118
}
118119

119120
// A queue of packets waiting to send to players tracking this human
120-
private final Map<UUID, List<Stream<Packet<?>>>> playerPacketMap = new HashMap<>();
121+
private final Map<UUID, List<Stream<Packet<? super ClientGamePacketListener>>>> playerPacketMap = new HashMap<>();
121122

122123
private ResolvableProfile fakeProfile;
123124
private boolean aiDisabled = false, leftHanded = false;
@@ -398,8 +399,7 @@ private void respawnOnClient() {
398399
this.pushPackets(new ClientboundRemoveEntitiesPacket(this.getId()), this.createPlayerListPacket(EnumSet.allOf(ClientboundPlayerInfoUpdatePacket.Action.class)));
399400
this.pushPackets(this.getAddEntityPacket(new ServerEntity(
400401
(ServerLevel) this.level(),
401-
this, 1, true, packet -> {},
402-
(packet, list) -> {}
402+
this, 1, true, NoOpSynchronizer.INSTANCE
403403
)));
404404
}
405405

@@ -445,7 +445,7 @@ public ClientboundPlayerInfoUpdatePacket createPlayerListPacket(final EnumSet<Cl
445445
*
446446
* @param packets All packets to send in a single tick
447447
*/
448-
public void pushPackets(final Packet<?>... packets) {
448+
public void pushPackets(final Packet<? super ClientGamePacketListener>... packets) {
449449
this.pushPackets(null, packets); // null = all players
450450
}
451451

@@ -456,8 +456,8 @@ public void pushPackets(final Packet<?>... packets) {
456456
* @param player The player tracking this human
457457
* @param packets All packets to send in a single tick
458458
*/
459-
public void pushPackets(final @Nullable ServerPlayer player, final Packet<?>... packets) {
460-
final List<Stream<Packet<?>>> queue;
459+
public void pushPackets(final @Nullable ServerPlayer player, final Packet<? super ClientGamePacketListener>... packets) {
460+
final List<Stream<Packet<? super ClientGamePacketListener>>> queue;
461461
if (player == null) {
462462
queue = this.playerPacketMap.computeIfAbsent(null, k -> new ArrayList<>());
463463
} else {
@@ -472,8 +472,8 @@ public void pushPackets(final @Nullable ServerPlayer player, final Packet<?>...
472472
* @param player The player to get packets for (or null for all players)
473473
* @return An array of packets to send in a single tick
474474
*/
475-
public Stream<Packet<?>> popQueuedPackets(final @Nullable ServerPlayer player) {
476-
final List<Stream<Packet<?>>> queue = this.playerPacketMap.get(player == null ? null : player.getUUID());
475+
public Stream<Packet<? super ClientGamePacketListener>> popQueuedPackets(final @Nullable ServerPlayer player) {
476+
final List<Stream<Packet<? super ClientGamePacketListener>>> queue = this.playerPacketMap.get(player == null ? null : player.getUUID());
477477
return queue == null || queue.isEmpty() ? Stream.empty() : queue.remove(0);
478478
}
479479

src/main/java/org/spongepowered/common/world/SpongePositionSourceFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public PositionSource of(final Vector3i position) {
4343

4444
@Override
4545
public PositionSource of(final int x, final int y, final int z) {
46-
return (PositionSource) new BlockPositionSource(new BlockPos(x, y, z));
46+
return (PositionSource) (Object) new BlockPositionSource(new BlockPos(x, y, z));
4747
}
4848

4949
@Override

src/mixins/java/org/spongepowered/common/mixin/api/minecraft/world/level/LevelMixin_API.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package org.spongepowered.common.mixin.api.minecraft.world.level;
2626

27+
import com.google.common.collect.Iterables;
2728
import net.kyori.adventure.sound.Sound;
2829
import net.minecraft.core.BlockPos;
2930
import net.minecraft.core.RegistryAccess;
@@ -181,7 +182,8 @@ public Iterable<WorldChunk> loadedChunks() {
181182
if (chunkProvider instanceof ServerChunkCache) {
182183
final ChunkMapAccessor chunkManager = (ChunkMapAccessor) ((ServerChunkCache) chunkProvider).chunkMap;
183184
final List<WorldChunk> chunks = new ArrayList<>();
184-
chunkManager.invoker$getChunks().forEach(holder -> {
185+
final var visibleChunks = chunkManager.accessor$visibleChunkMap();
186+
Iterables.unmodifiableIterable(visibleChunks.values()).forEach(holder -> {
185187
final WorldChunk chunk = (WorldChunk) holder.getTickingChunk();
186188
if (chunk != null) {
187189
chunks.add(chunk);

src/mixins/java/org/spongepowered/common/mixin/core/server/level/ChunkMap_TrackedEntityMixin.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
2929
import com.llamalad7.mixinextras.sugar.Local;
3030
import net.minecraft.network.protocol.Packet;
31+
import net.minecraft.network.protocol.game.ClientGamePacketListener;
3132
import net.minecraft.server.level.ServerPlayer;
3233
import net.minecraft.server.network.ServerGamePacketListenerImpl;
3334
import net.minecraft.server.network.ServerPlayerConnection;
@@ -57,12 +58,12 @@ public abstract class ChunkMap_TrackedEntityMixin {
5758
* 2) We already have the players being iterated
5859
* 3) This achieves the same functionality without adding new accessors etc.
5960
*/
60-
@Inject(method = "broadcast(Lnet/minecraft/network/protocol/Packet;)V", at = @At(value = "INVOKE", shift = At.Shift.AFTER,
61+
@Inject(method = "sendToTrackingPlayers(Lnet/minecraft/network/protocol/Packet;)V", at = @At(value = "INVOKE", shift = At.Shift.AFTER,
6162
target = "Lnet/minecraft/server/network/ServerPlayerConnection;send(Lnet/minecraft/network/protocol/Packet;)V"))
6263
private void impl$sendQueuedHumanPackets(final CallbackInfo ci, @Local final ServerPlayerConnection connection) {
6364
if (this.entity instanceof HumanEntity && connection instanceof ServerGamePacketListenerImpl) {
6465
final ServerPlayer player = ((ServerGamePacketListenerImpl) connection).player;
65-
final Stream<Packet<?>> packets = ((HumanEntity) this.entity).popQueuedPackets(player);
66+
final Stream<Packet<? super ClientGamePacketListener>> packets = ((HumanEntity) this.entity).popQueuedPackets(player);
6667
packets.forEach(player.connection::send);
6768
}
6869
}
@@ -74,7 +75,7 @@ public abstract class ChunkMap_TrackedEntityMixin {
7475
* entity is being "removed" from clients by way of literally being mimiced being
7576
* "untracked". This safeguards the players being updated erroneously.
7677
*/
77-
@Inject(method = "broadcast(Lnet/minecraft/network/protocol/Packet;)V", at = @At("HEAD"), cancellable = true)
78+
@Inject(method = "sendToTrackingPlayers(Lnet/minecraft/network/protocol/Packet;)V", at = @At("HEAD"), cancellable = true)
7879
private void impl$ignoreVanished(final Packet<?> packet, final CallbackInfo ci) {
7980
if (this.entity instanceof VanishableBridge) {
8081
if (((VanishableBridge) this.entity).bridge$vanishState().invisible()) {

src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerEntityMixin.java

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
2828
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
2929
import net.minecraft.network.protocol.Packet;
30+
import net.minecraft.network.protocol.game.ClientGamePacketListener;
3031
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
3132
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
3233
import net.minecraft.network.syncher.SynchedEntityData;
@@ -45,26 +46,33 @@
4546
import org.spongepowered.asm.mixin.injection.Redirect;
4647
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
4748
import org.spongepowered.common.accessor.world.entity.LivingEntityAccessor;
48-
import org.spongepowered.common.bridge.data.VanishableBridge;
4949
import org.spongepowered.common.bridge.server.level.ServerPlayerBridge;
50+
import org.spongepowered.common.data.datasync.VanishedFilteringSynchronizer;
5051
import org.spongepowered.common.entity.living.human.HumanEntity;
5152

53+
import java.lang.ref.WeakReference;
5254
import java.util.Collection;
5355
import java.util.EnumSet;
5456
import java.util.List;
55-
import java.util.function.BiConsumer;
5657
import java.util.function.Consumer;
58+
import java.util.function.Predicate;
5759
import java.util.stream.Stream;
5860

5961
@Mixin(ServerEntity.class)
6062
public abstract class ServerEntityMixin {
6163

6264
// @formatter:off
6365
@Shadow @Final private Entity entity;
64-
@Shadow @Final @Mutable private Consumer<Packet<?>> broadcast;
66+
@Shadow @Final @Mutable private ServerEntity.Synchronizer synchronizer;
6567
// @formatter:on
6668

6769
/**
70+
* @param serverLevel The world
71+
* @param entity The entity being tracked
72+
* @param trackingRange The update frequency
73+
* @param trackMovementDeltas Whether velocity updates are sent
74+
* @param broadcaster The consumer (a method handle for EntityTracker#sendToAllTracking)
75+
* @param ci The callback info
6876
* @author gabizou
6977
* @reason Because the packets for *most* all entity updates are handled
7078
* through this consumer tick, basically all the players tracking the
@@ -77,25 +85,13 @@ public abstract class ServerEntityMixin {
7785
* any and all players tracking our tracked entity by filtering the consumer first,
7886
* then as a fail safe, the EntityTracker mixin. Meanwhile, all other states are updated
7987
* just fine.
80-
*
81-
* @param serverLevel The world
82-
* @param entity The entity being tracked
83-
* @param trackingRange The update frequency
84-
* @param trackMovementDeltas Whether velocity updates are sent
85-
* @param broadcaster The consumer (a method handle for EntityTracker#sendToAllTracking)
86-
* @param ci The callback info
8788
*/
8889
@Inject(method = "<init>", at = @At("TAIL"))
89-
private void impl$wrapConsumer(final ServerLevel serverLevel, final Entity entity, final int trackingRange,
90-
final boolean trackMovementDeltas, final Consumer<Packet<?>> broadcaster,
91-
final BiConsumer<?, ?> filter, final CallbackInfo ci) {
92-
this.broadcast = (packet) -> {
93-
if (this.entity instanceof VanishableBridge bridge) {
94-
if (!bridge.bridge$vanishState().invisible()) {
95-
broadcaster.accept(packet);
96-
}
97-
}
98-
};
90+
private void impl$wrapConsumer(
91+
final ServerLevel serverLevel, final Entity entity, final int trackingRange,
92+
final boolean trackMovementDeltas, final ServerEntity.Synchronizer broadcaster,
93+
final CallbackInfo ci) {
94+
this.synchronizer = new VanishedFilteringSynchronizer(broadcaster, new WeakReference<>(this.entity));
9995
}
10096

10197
@Inject(method = "removePairing", at = @At("RETURN"))
@@ -139,8 +135,8 @@ public abstract class ServerEntityMixin {
139135
if (!(this.entity instanceof final HumanEntity human)) {
140136
return;
141137
}
142-
final Stream<Packet<?>> packets = human.popQueuedPackets(null);
143-
packets.forEach(this.broadcast);
138+
final Stream<Packet<? super ClientGamePacketListener>> packets = human.popQueuedPackets(null);
139+
packets.forEach(this.synchronizer::sendToTrackingPlayers);
144140
// Note that this will further call in ChunkManager_EntityTrackerMixin
145141
// for any player specific packets to send.
146142
}
@@ -169,15 +165,19 @@ public abstract class ServerEntityMixin {
169165
return packed;
170166
}
171167

172-
@WrapOperation(method = "sendChanges", at = @At(value = "INVOKE", target = "Ljava/util/function/BiConsumer;accept(Ljava/lang/Object;Ljava/lang/Object;)V"))
173-
private void impl$sendSetPassengersToSelf(final BiConsumer<?, ?> instance, final Object packet, final Object ignored, final Operation<Void> original) {
168+
@WrapOperation(method = "sendChanges",
169+
at = @At(value = "INVOKE",
170+
target = "Lnet/minecraft/server/level/ServerEntity$Synchronizer;sendToTrackingPlayersFiltered(Lnet/minecraft/network/protocol/Packet;Ljava/util/function/Predicate;)V"))
171+
private void impl$sendSetPassengersToSelf(
172+
final ServerEntity.Synchronizer instance, final Packet<? super ClientGamePacketListener> packet,
173+
final Predicate<ServerPlayer> serverPlayerPredicate, final Operation<Void> original) {
174174
// When passengers are removed from a player entity, the target
175175
// is the player itself, and we need to synchronize it to them.
176176
// In vanilla, it is not possible to ride player entities
177177
// so we never end up hitting this code path.
178-
original.call(instance, packet, ignored);
178+
original.call(instance, packet, serverPlayerPredicate);
179179
if (this.entity instanceof final ServerPlayer player) {
180-
player.connection.send((Packet<?>) packet);
180+
player.connection.send(packet);
181181
}
182182
}
183183
}

0 commit comments

Comments
 (0)