Skip to content

Commit

Permalink
Only sync to relevant players. Initial BE and chunk sync
Browse files Browse the repository at this point in the history
  • Loading branch information
Technici4n committed Jan 6, 2025
1 parent f34b5b2 commit b8b1006
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 37 deletions.
21 changes: 21 additions & 0 deletions patches/net/minecraft/server/level/ChunkMap.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,27 @@
EntityType<?> entitytype = p_140200_.getType();
int i = entitytype.clientTrackingRange() * 16;
if (i != 0) {
@@ -1240,6 +_,20 @@
});
}

+ // Neo: Getter for players watching an entity.
+ public List<ServerPlayer> getPlayersWatching(Entity entity) {
+ var trackedEntity = entityMap.get(entity.getId());
+ if (trackedEntity != null) {
+ var ret = new java.util.ArrayList<ServerPlayer>(trackedEntity.seenBy.size());
+ for (var connection : trackedEntity.seenBy) {
+ ret.add(connection.getPlayer());
+ }
+ return List.copyOf(ret);
+ } else {
+ return List.of();
+ }
+ }
+
class DistanceManager extends net.minecraft.server.level.DistanceManager {
protected DistanceManager(Executor p_140459_, Executor p_140460_) {
super(p_140459_, p_140460_);
@@ -1354,5 +_,20 @@
this.updatePlayer(serverplayer);
}
Expand Down
2 changes: 1 addition & 1 deletion patches/net/minecraft/server/level/ServerLevel.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@
+
+ @Override
+ public final void syncData(net.neoforged.neoforge.attachment.AttachmentType<?> type) {
+ net.neoforged.neoforge.attachment.AttachmentInternals.syncAttachmentUpdate(this, this, type);
+ net.neoforged.neoforge.attachment.AttachmentInternals.syncLevelUpdate(this, type);
+ }
+
+ private final net.neoforged.neoforge.capabilities.CapabilityListenerHolder capListenerHolder = new net.neoforged.neoforge.capabilities.CapabilityListenerHolder();
Expand Down
2 changes: 1 addition & 1 deletion patches/net/minecraft/world/entity/Entity.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@
+ @Override
+ public final void syncData(net.neoforged.neoforge.attachment.AttachmentType<?> type) {
+ if (level instanceof ServerLevel serverLevel) {
+ net.neoforged.neoforge.attachment.AttachmentInternals.syncAttachmentUpdate(this, serverLevel, type);
+ net.neoforged.neoforge.attachment.AttachmentInternals.syncEntityUpdate(this, type);
+ }
+ }
+
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
}

public boolean triggerEvent(int p_58889_, int p_58890_) {
@@ -234,6 +_,34 @@
@@ -234,6 +_,32 @@
return this.type;
}

Expand All @@ -96,9 +96,7 @@
+
+ @Override
+ public final void syncData(net.neoforged.neoforge.attachment.AttachmentType<?> type) {
+ if (level instanceof ServerLevel serverLevel) {
+ net.neoforged.neoforge.attachment.AttachmentInternals.syncAttachmentUpdate(this, serverLevel, type);
+ }
+ net.neoforged.neoforge.attachment.AttachmentInternals.syncBlockEntityUpdate(this, type);
+ }
+
@Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
+ }
+
+ @org.jetbrains.annotations.ApiStatus.Internal
+ protected net.neoforged.neoforge.attachment.AttachmentHolder.AsField getAttachmentHolder() {
+ public net.neoforged.neoforge.attachment.AttachmentHolder.AsField getAttachmentHolder() {
+ return attachmentHolder;
+ }
+
Expand Down
6 changes: 2 additions & 4 deletions patches/net/minecraft/world/level/chunk/LevelChunk.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
this.blockEntities.values().forEach(p_187988_ -> {
if (this.level instanceof ServerLevel serverlevel) {
this.addGameEventListener(p_187988_, serverlevel);
@@ -694,6 +_,21 @@
@@ -694,6 +_,19 @@
return new LevelChunk.BoundTickingBlockEntity<>(p_156376_, p_156377_);
}

Expand All @@ -134,9 +134,7 @@
+
+ @Override
+ public final void syncData(net.neoforged.neoforge.attachment.AttachmentType<?> type) {
+ if (level instanceof ServerLevel serverLevel) {
+ net.neoforged.neoforge.attachment.AttachmentInternals.syncAttachmentUpdate(getAttachmentHolder(), serverLevel, type);
+ }
+ net.neoforged.neoforge.attachment.AttachmentInternals.syncChunkUpdate(this, getAttachmentHolder(), type);
+ }
+
class BoundTickingBlockEntity<T extends BlockEntity> implements TickingBlockEntity {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBundlePacket;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.LevelChunk;
Expand All @@ -31,8 +33,8 @@
import net.neoforged.neoforge.common.util.FriendlyByteBufUtil;
import net.neoforged.neoforge.event.entity.living.LivingConversionEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.level.ChunkWatchEvent;
import net.neoforged.neoforge.internal.versions.neoforge.NeoForgeVersion;
import net.neoforged.neoforge.network.PacketDistributor;
import net.neoforged.neoforge.network.connection.ConnectionType;
import net.neoforged.neoforge.network.payload.SyncAttachmentsPayload;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
Expand Down Expand Up @@ -114,27 +116,58 @@ static SyncAttachmentsPayload.Target syncTarget(AttachmentHolder holder) {
};
}

public static <T> void syncAttachmentUpdate(AttachmentHolder holder, ServerLevel level, AttachmentType<T> type) {
if (type.syncHandler == null) {
private static <T> void syncUpdate(AttachmentHolder holder, AttachmentType<T> type, List<ServerPlayer> players) {
RegistryAccess registryAccess = null;
for (var player : players) {
if (type.syncHandler.sendToPlayer(holder.getExposedHolder(), player)) {
registryAccess = player.registryAccess();
break;
}
}
// This also serves as a short-circuit if there are no players to sync data to.
if (registryAccess == null) {
return;
}
var value = holder.getData(type); // TODO: what if data is missing?
for (var player : level.players()) { // TODO: only sync to relevant players? e.g. only players that see a specific chunk
List<AttachmentType<?>> syncedTypes = new ArrayList<>(1);
var data = FriendlyByteBufUtil.writeCustomData(buf -> {
int indexBefore = buf.writerIndex();
type.syncHandler.write(buf, value, player, AttachmentSyncReason.ENTITY_SYNC_REQUESTED);
if (indexBefore < buf.writerIndex()) {
// Actually wrote something
syncedTypes.add(type);
}
}, level.registryAccess());
if (!syncedTypes.isEmpty()) {
PacketDistributor.sendToPlayer(player, new SyncAttachmentsPayload(syncTarget(holder), syncedTypes, data));
var data = FriendlyByteBufUtil.writeCustomData(buf -> {
// TODO: what if data is missing?
type.syncHandler.write(buf, holder.getData(type), false);
}, registryAccess);
var packet = new SyncAttachmentsPayload(syncTarget(holder), List.of(type), data).toVanillaClientbound();
for (var player : players) {
if (type.syncHandler.sendToPlayer(holder.getExposedHolder(), player)) {
player.connection.send(packet);
}
}
}

public static void syncBlockEntityUpdate(BlockEntity blockEntity, AttachmentType<?> type) {
if (type.syncHandler == null || !(blockEntity.getLevel() instanceof ServerLevel serverLevel)) {
return;
}
syncUpdate(blockEntity, type, serverLevel.getChunkSource().chunkMap.getPlayers(new ChunkPos(blockEntity.getBlockPos()), false));
}

public static void syncChunkUpdate(LevelChunk chunk, AttachmentHolder.AsField holder, AttachmentType<?> type) {
if (type.syncHandler == null || !(chunk.getLevel() instanceof ServerLevel serverLevel)) {
return;
}
syncUpdate(holder, type, serverLevel.getChunkSource().chunkMap.getPlayers(chunk.getPos(), false));
}

public static void syncEntityUpdate(Entity entity, AttachmentType<?> type) {
if (type.syncHandler == null || !(entity.level() instanceof ServerLevel serverLevel)) {
return;
}
syncUpdate(entity, type, serverLevel.getChunkSource().chunkMap.getPlayersWatching(entity));
}

public static void syncLevelUpdate(ServerLevel level, AttachmentType<?> type) {
if (type.syncHandler == null) {
return;
}
syncUpdate(level, type, level.players());
}

@Nullable
private static SyncAttachmentsPayload syncInitialAttachments(AttachmentHolder holder, ServerPlayer to) {
if (holder.attachments == null) {
Expand All @@ -155,7 +188,7 @@ private static SyncAttachmentsPayload syncInitialAttachments(AttachmentHolder ho
var syncHandler = (IAttachmentSyncHandler<Object>) type.syncHandler;
if (syncHandler != null) {
int indexBefore = buf.writerIndex();
syncHandler.write(buf, entry.getValue(), to, AttachmentSyncReason.NEW_ENTITY);
syncHandler.write(buf, entry.getValue(), true);
if (indexBefore < buf.writerIndex()) {
// Actually wrote something
syncedTypes.add(type);
Expand All @@ -166,6 +199,24 @@ private static SyncAttachmentsPayload syncInitialAttachments(AttachmentHolder ho
return new SyncAttachmentsPayload(syncTarget(holder), syncedTypes, data);
}

@SubscribeEvent
public static void onChunkSent(ChunkWatchEvent.Sent event) {
List<Packet<? super ClientGamePacketListener>> packets = new ArrayList<>();
var chunkPayload = syncInitialAttachments(event.getChunk().getAttachmentHolder(), event.getPlayer());
if (chunkPayload != null) {
packets.add(chunkPayload.toVanillaClientbound());
}
for (var blockEntity : event.getChunk().getBlockEntities().values()) {
var blockEntityPayload = syncInitialAttachments(blockEntity, event.getPlayer());
if (blockEntityPayload != null) {
packets.add(blockEntityPayload.toVanillaClientbound());
}
}
if (!packets.isEmpty()) {
event.getPlayer().connection.send(new ClientboundBundlePacket(packets));
}
}

public static void sendEntityPairingData(Entity entity, ServerPlayer to, Consumer<Packet<? super ClientGamePacketListener>> packetConsumer) {
var packet = syncInitialAttachments(entity, to);
if (packet != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import net.minecraft.nbt.Tag;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
Expand Down Expand Up @@ -248,7 +247,7 @@ public Builder<T> sync(StreamCodec<? super RegistryFriendlyByteBuf, T> streamCod
Objects.requireNonNull(streamCodec);
return sync(new IAttachmentSyncHandler<>() {
@Override
public void write(RegistryFriendlyByteBuf buf, T attachment, ServerPlayer to, AttachmentSyncReason reason) {
public void write(RegistryFriendlyByteBuf buf, T attachment, boolean initialSync) {
streamCodec.encode(buf, attachment);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.Nullable;

import java.util.function.Supplier;

/**
* Manages how data attachments are written (on the server) and read (on the client) from packets.
*
Expand All @@ -21,8 +19,11 @@
* {@link IAttachmentHolder#syncData(AttachmentType)} can be called to trigger syncing.
*/
public interface IAttachmentSyncHandler<T> {
// TODO: pass target player
void write(RegistryFriendlyByteBuf buf, T attachment, ServerPlayer to, AttachmentSyncReason reason);
default boolean sendToPlayer(IAttachmentHolder holder, ServerPlayer to) {
return true;
}

void write(RegistryFriendlyByteBuf buf, T attachment, boolean initialSync);

// TODO: we could also return void and let the sync handler call .setData(type, xxx). But that means passing the type somehow.
@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.attachment.AttachmentSyncReason;
import net.neoforged.neoforge.attachment.AttachmentType;
import net.neoforged.neoforge.attachment.IAttachmentHolder;
import net.neoforged.neoforge.attachment.IAttachmentSyncHandler;
Expand All @@ -43,7 +41,7 @@ public class AttachmentSyncTest {
// TODO: use streamcodec version at some point
.sync(new IAttachmentSyncHandler<Integer>() {
@Override
public void write(RegistryFriendlyByteBuf buf, Integer attachment, ServerPlayer to, AttachmentSyncReason reason) {
public void write(RegistryFriendlyByteBuf buf, Integer attachment, boolean initialSync) {
buf.writeInt(attachment);
}

Expand Down

0 comments on commit b8b1006

Please sign in to comment.