Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a RegistryByteBuf for attachment syncing #4223

Open
wants to merge 6 commits into
base: 1.21.4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import com.mojang.serialization.Codec;
import org.jetbrains.annotations.ApiStatus;

import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.util.Identifier;

Expand Down Expand Up @@ -157,7 +157,7 @@ public interface Builder<A> {
* @param syncPredicate an {@link AttachmentSyncPredicate} determining with which clients to synchronize data
* @return the builder
*/
AttachmentRegistry.Builder<A> syncWith(PacketCodec<PacketByteBuf, A> packetCodec, AttachmentSyncPredicate syncPredicate);
AttachmentRegistry.Builder<A> syncWith(PacketCodec<? super RegistryByteBuf, A> packetCodec, AttachmentSyncPredicate syncPredicate);

/**
* Builds and registers the {@link AttachmentType}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.util.Identifier;

Expand Down Expand Up @@ -80,7 +80,7 @@ public static class BuilderImpl<A> implements AttachmentRegistry.Builder<A> {
@Nullable
private Codec<A> persistenceCodec = null;
@Nullable
private PacketCodec<PacketByteBuf, A> packetCodec = null;
private PacketCodec<? super RegistryByteBuf, A> packetCodec = null;
@Nullable
private AttachmentSyncPredicate syncPredicate = null;
private boolean copyOnDeath = false;
Expand All @@ -107,7 +107,8 @@ public AttachmentRegistry.Builder<A> initializer(Supplier<A> initializer) {
return this;
}

public AttachmentRegistry.Builder<A> syncWith(PacketCodec<PacketByteBuf, A> packetCodec, AttachmentSyncPredicate syncPredicate) {
@Deprecated
public AttachmentRegistry.Builder<A> syncWith(PacketCodec<? super RegistryByteBuf, A> packetCodec, AttachmentSyncPredicate syncPredicate) {
Objects.requireNonNull(packetCodec, "packet codec cannot be null");
Objects.requireNonNull(syncPredicate, "sync predicate cannot be null");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.jetbrains.annotations.Nullable;

import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.server.network.ServerPlayerEntity;

Expand Down Expand Up @@ -93,4 +94,6 @@ default void fabric_markChanged(AttachmentType<?> type) {
default boolean fabric_shouldTryToSync() {
throw new UnsupportedOperationException("Implemented via mixin");
}

DynamicRegistryManager fabric_getDynamicRegistryManager();
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import com.mojang.serialization.Codec;
import org.jetbrains.annotations.Nullable;

import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.util.Identifier;

Expand All @@ -32,7 +32,7 @@ public record AttachmentTypeImpl<A>(
Identifier identifier,
@Nullable Supplier<A> initializer,
@Nullable Codec<A> persistenceCodec,
@Nullable PacketCodec<PacketByteBuf, A> packetCodec,
@Nullable PacketCodec<? super RegistryByteBuf, A> packetCodec,
@Nullable AttachmentSyncPredicate syncPredicate,
boolean copyOnDeath
) implements AttachmentType<A> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import io.netty.buffer.Unpooled;
import org.jetbrains.annotations.Nullable;

import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
Expand Down Expand Up @@ -57,12 +58,20 @@ public record AttachmentChange(AttachmentTargetInfo<?> targetInfo, AttachmentTyp
private static final int MAX_DATA_SIZE_IN_BYTES = CustomPayloadS2CPacketAccessor.getMaxPayloadSize() - MAX_PADDING_SIZE_IN_BYTES;

@SuppressWarnings("unchecked")
public static AttachmentChange create(AttachmentTargetInfo<?> targetInfo, AttachmentType<?> type, @Nullable Object value) {
PacketCodec<PacketByteBuf, Object> codec = (PacketCodec<PacketByteBuf, Object>) ((AttachmentTypeImpl<?>) type).packetCodec();
public static AttachmentChange create(AttachmentTargetInfo<?> targetInfo, AttachmentType<?> type, @Nullable Object value, DynamicRegistryManager dynamicRegistryManager) {
PacketCodec<? super RegistryByteBuf, Object> codec = (PacketCodec<? super RegistryByteBuf, Object>) ((AttachmentTypeImpl<?>) type).packetCodec();
Objects.requireNonNull(codec, "attachment packet codec cannot be null");
Objects.requireNonNull(dynamicRegistryManager, "dynamic registry manager cannot be null");

RegistryByteBuf buf = new RegistryByteBuf(PacketByteBufs.create(), dynamicRegistryManager);

if (value != null) {
buf.writeBoolean(true);
codec.encode(buf, value);
} else {
buf.writeBoolean(false);
}

PacketByteBuf buf = PacketByteBufs.create();
buf.writeOptional(Optional.ofNullable(value), codec);
byte[] encoded = buf.array();

if (encoded.length > MAX_DATA_SIZE_IN_BYTES) {
Expand Down Expand Up @@ -109,15 +118,21 @@ public static void partitionAndSendPackets(List<AttachmentChange> changes, Serve

@SuppressWarnings("unchecked")
@Nullable
public Object decodeValue() {
PacketCodec<PacketByteBuf, Object> codec = (PacketCodec<PacketByteBuf, Object>) ((AttachmentTypeImpl<?>) type).packetCodec();
public Object decodeValue(DynamicRegistryManager dynamicRegistryManager) {
PacketCodec<? super RegistryByteBuf, Object> codec = (PacketCodec<? super RegistryByteBuf, Object>) ((AttachmentTypeImpl<?>) type).packetCodec();
Objects.requireNonNull(codec, "codec was null");
Objects.requireNonNull(dynamicRegistryManager, "dynamic registry manager cannot be null");

RegistryByteBuf buf = new RegistryByteBuf(Unpooled.copiedBuffer(data), dynamicRegistryManager);

if (!buf.readBoolean()) {
return null;
}

PacketByteBuf buf = new PacketByteBuf(Unpooled.copiedBuffer(data));
return buf.readOptional(codec).orElse(null);
return codec.decode(buf);
}

public void apply(World world) {
targetInfo.getTarget(world).setAttached((AttachmentType<Object>) type, decodeValue());
targetInfo.getTarget(world).setAttached((AttachmentType<Object>) type, decodeValue(world.getRegistryManager()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public <T> T setAttached(AttachmentType<T> type, @Nullable T value) {
this.fabric_markChanged(type);

if (this.fabric_shouldTryToSync() && type.isSynced()) {
AttachmentChange change = AttachmentChange.create(fabric_getSyncTargetInfo(), type, value);
AttachmentChange change = AttachmentChange.create(fabric_getSyncTargetInfo(), type, value, fabric_getDynamicRegistryManager());
acknowledgeSyncedEntry(type, change);
this.fabric_syncChange(type, new AttachmentSyncPayloadS2C(List.of(change)));
}
Expand Down Expand Up @@ -118,7 +118,7 @@ public boolean fabric_hasPersistentAttachments() {

@Unique
private void acknowledgeSynced(AttachmentType<?> type, Object value) {
acknowledgeSyncedEntry(type, AttachmentChange.create(fabric_getSyncTargetInfo(), type, value));
acknowledgeSyncedEntry(type, AttachmentChange.create(fabric_getSyncTargetInfo(), type, value, fabric_getDynamicRegistryManager()));
}

@Unique
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import net.minecraft.block.entity.BlockEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
Expand Down Expand Up @@ -95,4 +96,9 @@ public boolean fabric_shouldTryToSync() {
// Persistent attachments are read at a time with no world
return !this.hasWorld() || !this.world.isClient();
}

@Override
public DynamicRegistryManager fabric_getDynamicRegistryManager() {
return this.world.getRegistryManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;

import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkStatus;
Expand Down Expand Up @@ -67,4 +68,10 @@ public boolean fabric_shouldTryToSync() {
// ProtoChunk or EmptyChunk
return false;
}

@Override
public DynamicRegistryManager fabric_getDynamicRegistryManager() {
// Should never happen as this is only used for sync
throw new UnsupportedOperationException("Chunk does not have a DynamicRegistryManager.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import net.minecraft.entity.Entity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.world.World;

Expand Down Expand Up @@ -89,4 +90,9 @@ public void fabric_syncChange(AttachmentType<?> type, AttachmentSyncPayloadS2C p
public boolean fabric_shouldTryToSync() {
return !this.getWorld().isClient();
}

@Override
public DynamicRegistryManager fabric_getDynamicRegistryManager() {
return this.getWorld().getRegistryManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,9 @@ public void fabric_syncChange(AttachmentType<?> type, AttachmentSyncPayloadS2C p
public AttachmentTargetInfo<?> fabric_getSyncTargetInfo() {
return AttachmentTargetInfo.WorldTarget.INSTANCE;
}

@Override
public DynamicRegistryManager fabric_getDynamicRegistryManager() {
return getRegistryManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import net.minecraft.block.entity.BlockEntity;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
Expand Down Expand Up @@ -83,4 +84,9 @@ public void fabric_syncChange(AttachmentType<?> type, AttachmentSyncPayloadS2C p
public boolean fabric_shouldTryToSync() {
return !this.world.isClient();
}

@Override
public DynamicRegistryManager fabric_getDynamicRegistryManager() {
return world.getRegistryManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;

import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.world.World;

import net.fabricmc.fabric.impl.attachment.AttachmentTargetImpl;
Expand All @@ -28,8 +29,16 @@ abstract class WorldMixin implements AttachmentTargetImpl {
@Shadow
public abstract boolean isClient();

@Shadow
public abstract DynamicRegistryManager getRegistryManager();

@Override
public boolean fabric_shouldTryToSync() {
return !this.isClient();
}

@Override
public DynamicRegistryManager fabric_getDynamicRegistryManager() {
return getRegistryManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.spongepowered.asm.mixin.Shadow;

import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.world.chunk.WorldChunk;
Expand Down Expand Up @@ -103,4 +104,9 @@ public void fabric_syncChange(AttachmentType<?> type, AttachmentSyncPayloadS2C p
public void fabric_markChanged(AttachmentType<?> type) {
((AttachmentTargetImpl) wrapped).fabric_markChanged(type);
}

@Override
public DynamicRegistryManager fabric_getDynamicRegistryManager() {
return ((AttachmentTargetImpl) wrapped).fabric_getDynamicRegistryManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,15 @@
import net.minecraft.command.argument.BlockPosArgumentType;
import net.minecraft.command.argument.ColumnPosArgumentType;
import net.minecraft.command.argument.EntityArgumentType;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
Expand All @@ -63,6 +66,7 @@
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;

public class AttachmentTestMod implements ModInitializer {
Expand All @@ -80,28 +84,35 @@ public class AttachmentTestMod implements ModInitializer {
builder -> builder
.initializer(() -> false)
.persistent(Codec.BOOL)
.syncWith(PacketCodecs.BOOLEAN.cast(), AttachmentSyncPredicate.all())
.syncWith(PacketCodecs.BOOLEAN, AttachmentSyncPredicate.all())
);
public static final AttachmentType<Boolean> SYNCED_WITH_TARGET = AttachmentRegistry.create(
Identifier.of(MOD_ID, "synced_target"),
builder -> builder
.initializer(() -> false)
.persistent(Codec.BOOL)
.syncWith(PacketCodecs.BOOLEAN.cast(), AttachmentSyncPredicate.targetOnly())
.syncWith(PacketCodecs.BOOLEAN, AttachmentSyncPredicate.targetOnly())
);
public static final AttachmentType<Boolean> SYNCED_EXCEPT_TARGET = AttachmentRegistry.create(
Identifier.of(MOD_ID, "synced_except_target"),
builder -> builder
.initializer(() -> false)
.persistent(Codec.BOOL)
.syncWith(PacketCodecs.BOOLEAN.cast(), AttachmentSyncPredicate.allButTarget())
.syncWith(PacketCodecs.BOOLEAN, AttachmentSyncPredicate.allButTarget())
);
public static final AttachmentType<Boolean> SYNCED_CREATIVE_ONLY = AttachmentRegistry.create(
Identifier.of(MOD_ID, "synced_custom"),
builder -> builder
.initializer(() -> false)
.persistent(Codec.BOOL)
.syncWith(PacketCodecs.BOOLEAN.cast(), (target, player) -> player.isCreative())
.syncWith(PacketCodecs.BOOLEAN, (target, player) -> player.isCreative())
);
public static final AttachmentType<ItemStack> SYNCED_ITEM = AttachmentRegistry.create(
Identifier.of(MOD_ID, "synced_item"),
builder -> builder
.initializer(() -> ItemStack.EMPTY)
.persistent(ItemStack.CODEC)
.syncWith(ItemStack.OPTIONAL_PACKET_CODEC, AttachmentSyncPredicate.all())
);
public static final SimpleCommandExceptionType TARGET_NOT_FOUND = new SimpleCommandExceptionType(Text.literal("Target not found"));

Expand Down Expand Up @@ -196,6 +207,12 @@ public void onInitialize() {
.then(buildCommandForKind("others_only", "all but self", SYNCED_EXCEPT_TARGET))
.then(buildCommandForKind("creative_only", "creative players only", SYNCED_CREATIVE_ONLY))
));

ServerEntityEvents.EQUIPMENT_CHANGE.register((livingEntity, equipmentSlot, previousStack, currentStack) -> {
if (equipmentSlot == EquipmentSlot.HEAD && livingEntity instanceof ServerPlayerEntity player) {
player.setAttached(SYNCED_ITEM, currentStack);
}
});
}

private static LiteralArgumentBuilder<ServerCommandSource> buildCommandForKind(String id, String syncedWith, AttachmentType<Boolean> type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import net.minecraft.command.argument.UuidArgumentType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Colors;
import net.minecraft.util.math.BlockPos;
Expand Down Expand Up @@ -99,6 +100,11 @@ private static <T extends AttachmentTarget> void displayClientAttachmentInfo(
Text.literal("Synced-with-creative attachment: %s".formatted(attCustom))
.withColor(attCustom ? target instanceof PlayerEntity p && p.isCreative() ? Colors.GREEN : Colors.RED : Colors.WHITE)
);
ItemStack stack = target.getAttachedOrCreate(AttachmentTestMod.SYNCED_ITEM);
context.getSource().sendFeedback(
Text.literal("Synced-item attachment: %s".formatted(stack))
.withColor(attOther ? target != MinecraftClient.getInstance().player ? Colors.GREEN : Colors.RED : Colors.WHITE)
);
}

@Override
Expand Down
Loading