Sync tag ingredients directly if ModernFix is installed on both sides
This commit is contained in:
parent
536eb03b50
commit
01d2582c44
|
|
@ -66,5 +66,6 @@ accessible field net/minecraft/server/packs/resources/ProfiledReloadInstance$Sta
|
|||
accessible field net/minecraft/server/packs/resources/ProfiledReloadInstance$State reloadNanos Ljava/util/concurrent/atomic/AtomicLong;
|
||||
|
||||
accessible class net/minecraft/world/item/crafting/Ingredient$Value
|
||||
accessible field net/minecraft/world/item/crafting/Ingredient$TagValue tag Lnet/minecraft/tags/TagKey;
|
||||
accessible class net/minecraft/world/item/crafting/Ingredient$ItemValue
|
||||
accessible class net/minecraft/client/searchtree/SearchRegistry$TreeEntry
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.smart_ingredient_sync;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.ConnectionProtocol;
|
||||
import net.minecraft.network.PacketSendListener;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket;
|
||||
import org.embeddedt.modernfix.forge.packet.PacketHandler;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
@Mixin(Connection.class)
|
||||
public class ConnectionMixin {
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason Provide context to the ingredient serializer about whether the enhanced sync protocol is supported.
|
||||
*/
|
||||
@WrapMethod(method = "doSendPacket")
|
||||
private void modernfix$checkClientPresence(Packet<?> packet, @Nullable PacketSendListener sendListener, ConnectionProtocol newProtocol, ConnectionProtocol currentProtocol, Operation<Void> original) {
|
||||
if (packet instanceof ClientboundUpdateRecipesPacket && PacketHandler.INGREDIENT_SYNC.isRemotePresent((Connection)(Object)this)) {
|
||||
PacketHandler.CLIENT_HAS_SMART_INGREDIENT_SYNC.set(true);
|
||||
try {
|
||||
original.call(packet, sendListener, newProtocol, currentProtocol);
|
||||
} finally {
|
||||
PacketHandler.CLIENT_HAS_SMART_INGREDIENT_SYNC.set(false);
|
||||
}
|
||||
} else {
|
||||
original.call(packet, sendListener, newProtocol, currentProtocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.smart_ingredient_sync;
|
||||
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import org.embeddedt.modernfix.forge.packet.PacketHandler;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(Ingredient.class)
|
||||
public abstract class IngredientMixin {
|
||||
@Shadow public abstract boolean isVanilla();
|
||||
|
||||
@Shadow @Final private Ingredient.Value[] values;
|
||||
|
||||
@Unique
|
||||
private static final ResourceLocation MODERNFIX_TAG_VALUE = new ResourceLocation("modernfix", "tag_value");
|
||||
|
||||
@Inject(method = "toNetwork",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true)
|
||||
private void checkForVanillaTagIngredient(FriendlyByteBuf buf, CallbackInfo ci) {
|
||||
if (!PacketHandler.CLIENT_HAS_SMART_INGREDIENT_SYNC.get() || !this.isVanilla()) {
|
||||
return;
|
||||
}
|
||||
Ingredient.Value[] values = this.values;
|
||||
if (values.length == 1 && values[0] instanceof Ingredient.TagValue tagValue) {
|
||||
var optionalHolderSet = BuiltInRegistries.ITEM.getTag(tagValue.tag);
|
||||
if (optionalHolderSet.isEmpty()) {
|
||||
// Use default serialization logic for tags that do not exist
|
||||
return;
|
||||
}
|
||||
|
||||
// Encode this as our tag ingredient type instead of using vanilla's flattening logic.
|
||||
ci.cancel();
|
||||
buf.writeVarInt(-1);
|
||||
buf.writeResourceLocation(MODERNFIX_TAG_VALUE);
|
||||
buf.writeResourceLocation(tagValue.tag.location());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "fromNetwork", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/FriendlyByteBuf;readResourceLocation()Lnet/minecraft/resources/ResourceLocation;", ordinal = 0), cancellable = true)
|
||||
private static void deserializeModernFixTagValue(FriendlyByteBuf buffer, CallbackInfoReturnable<Ingredient> cir) {
|
||||
int readerIndex = buffer.readerIndex();
|
||||
var type = buffer.readResourceLocation();
|
||||
if (!type.equals(MODERNFIX_TAG_VALUE)) {
|
||||
// Allow Forge to read the original packet
|
||||
buffer.readerIndex(readerIndex);
|
||||
return;
|
||||
}
|
||||
var tag = buffer.readResourceLocation();
|
||||
cir.setReturnValue(Ingredient.of(TagKey.create(Registries.ITEM, tag)));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package org.embeddedt.modernfix.forge.mixin.perf.smart_ingredient_sync;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.llamalad7.mixinextras.sugar.Share;
|
||||
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.server.players.PlayerList;
|
||||
import org.embeddedt.modernfix.ModernFix;
|
||||
import org.embeddedt.modernfix.forge.packet.PacketHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.Slice;
|
||||
|
||||
@Mixin(PlayerList.class)
|
||||
public class PlayerListMixin {
|
||||
/**
|
||||
* @author embeddedt
|
||||
* @reason Ensure the tag packet is always sent before the recipe packet (like it is after /reload).
|
||||
*/
|
||||
@Redirect(method = "placeNewPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V"),
|
||||
slice = @Slice(
|
||||
from = @At(value = "NEW", target = "(Lnet/minecraft/server/players/PlayerList;Lnet/minecraft/server/level/ServerPlayer;)Lnet/minecraftforge/event/OnDatapackSyncEvent;"),
|
||||
to = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;sendPlayerPermissionLevel(Lnet/minecraft/server/level/ServerPlayer;)V")
|
||||
), expect = 2, allow = 2, require = 2)
|
||||
private void modernfix$switchTagAndRecipeOrder(ServerGamePacketListenerImpl instance, Packet<?> packet, @Local(ordinal = 0, argsOnly = true) Connection netManager, @Local(ordinal = 0, argsOnly = true) ServerPlayer player, @Share("deferred") LocalRef<Packet<?>> pktRef) {
|
||||
if (!(packet instanceof ClientboundUpdateRecipesPacket) && !(packet instanceof ClientboundUpdateTagsPacket)) {
|
||||
throw new AssertionError("Mixin injected in wrong place");
|
||||
}
|
||||
if (!PacketHandler.INGREDIENT_SYNC.isRemotePresent(netManager)) {
|
||||
instance.send(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet instanceof ClientboundUpdateRecipesPacket) {
|
||||
pktRef.set(packet);
|
||||
} else {
|
||||
ModernFix.LOGGER.info("Using enhanced recipe sync for player {}", player.getName().getString());
|
||||
// send tags
|
||||
instance.send(packet);
|
||||
// send recipes
|
||||
instance.send(pktRef.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,17 +13,21 @@ import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
public class PacketHandler {
|
||||
private static final String PROTOCOL_VERSION = "1";
|
||||
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
|
||||
new ResourceLocation(ModernFix.MODID, "main"),
|
||||
() -> PROTOCOL_VERSION,
|
||||
NetworkRegistry.acceptMissingOr(PROTOCOL_VERSION),
|
||||
NetworkRegistry.acceptMissingOr(PROTOCOL_VERSION)
|
||||
);
|
||||
public static final SimpleChannel INSTANCE = buildChannel("main", "1");
|
||||
public static final SimpleChannel INGREDIENT_SYNC = buildChannel("ingredient_sync", "1");
|
||||
public static final ThreadLocal<Boolean> CLIENT_HAS_SMART_INGREDIENT_SYNC = ThreadLocal.withInitial(() -> false);
|
||||
|
||||
private static SimpleChannel buildChannel(String name, String version) {
|
||||
return NetworkRegistry.newSimpleChannel(
|
||||
new ResourceLocation(ModernFix.MODID, name),
|
||||
() -> version,
|
||||
NetworkRegistry.acceptMissingOr(version),
|
||||
NetworkRegistry.acceptMissingOr(version)
|
||||
);
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
int id = 1;
|
||||
INSTANCE.registerMessage(id++, EntityIDSyncPacket.class, EntityIDSyncPacket::serialize, EntityIDSyncPacket::deserialize, PacketHandler::handleSyncPacket);
|
||||
INSTANCE.registerMessage(1, EntityIDSyncPacket.class, EntityIDSyncPacket::serialize, EntityIDSyncPacket::deserialize, PacketHandler::handleSyncPacket);
|
||||
}
|
||||
|
||||
private static void handleSyncPacket(EntityIDSyncPacket packet, Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user