Make default Entity.getAddPacket automatically use Forge's enhanced spawn packet if nessasary.

This spawn packet needs to be re-designed, it is effectively only there to hook into creating the new entity instance. This will be re-evaluated during the cleanup in 1.21+
This commit is contained in:
LexManos committed 2023-09-28 16:31:18 -07:00
1 parent 374dbc7a4b
commit fcf9088aa5
8 files changed
+78 -53

No files matched your search

@@ -30,6 +30,7 @@ import com.mojang.serialization.Dynamic;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Lifecycle;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
@@ -42,6 +43,7 @@ import net.minecraft.core.HolderSet;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.Connection;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
@@ -96,6 +98,7 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.syncher.EntityDataSerializer;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
import net.minecraft.world.item.alchemy.Potion;
@@ -116,6 +119,7 @@ import net.minecraftforge.common.util.BrainBuilder;
import net.minecraftforge.common.util.Lazy;
import net.minecraftforge.common.util.MavenVersionStringHelper;
import net.minecraftforge.common.util.MutableHashedLinkedMap;
import net.minecraftforge.entity.IEntityAdditionalSpawnData;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
import net.minecraftforge.event.DifficultyChangeEvent;
@@ -166,7 +170,10 @@ import net.minecraftforge.fml.util.thread.EffectiveSide;
import net.minecraftforge.network.ConnectionType;
import net.minecraftforge.network.ICustomPacket;
import net.minecraftforge.network.NetworkContext;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkInitialization;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.packets.SpawnEntity;
import net.minecraftforge.resource.ResourcePackLoader;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistry;
@@ -1251,4 +1258,16 @@ public class ForgeHooks {
LOGGER.info("Connected to a modded server.");
}
@ApiStatus.Internal
public static Packet<ClientGamePacketListener> getEntitySpawnPacket(Entity entity) {
if (!(entity instanceof IEntityAdditionalSpawnData add))
throw new IllegalArgumentException(entity.getClass() + " is not an instance of " + IEntityAdditionalSpawnData.class);
var play = NetworkInitialization.PLAY;
var msg = new SpawnEntity(entity);
var data = play.toBuffer(msg);
@SuppressWarnings("unchecked")
var pkt = (Packet<ClientGamePacketListener>)NetworkDirection.PLAY_TO_CLIENT.buildPacket(data, play.getName()).getThis();
return pkt;
}
}
@@ -38,7 +38,7 @@ public abstract class Channel<MSG> {
return NetworkContext.get(connection).getRemoteChannels().contains(getName());
}
protected abstract FriendlyByteBuf toBuffer(MSG message);
public abstract FriendlyByteBuf toBuffer(MSG message);
// Package private so we can call from ourselves.
Packet<?> toVanillaPacket(Connection connection, MSG message) {
@@ -42,7 +42,7 @@ public class EventNetworkChannel extends Channel<FriendlyByteBuf> {
}
@Override
protected FriendlyByteBuf toBuffer(FriendlyByteBuf message) {
public FriendlyByteBuf toBuffer(FriendlyByteBuf message) {
return message;
}
}
@@ -94,16 +94,16 @@ public class NetworkInitialization {
.consumerNetworkThread(CONTEXT, ForgePacketHandler::handleModMismatchData)
.add()
.messageBuilder(SpawnEntity.class)
.messageBuilder(SpawnEntity.class, NetworkDirection.PLAY_TO_CLIENT)
.decoder(SpawnEntity::decode)
.encoder(SpawnEntity::encode)
.consumerNetworkThread(SpawnEntity::handle)
.consumerMainThread(SpawnEntity::handle)
.add()
.messageBuilder(OpenContainer.class)
.decoder(OpenContainer::decode)
.encoder(OpenContainer::encode)
.consumerNetworkThread(OpenContainer::handle)
.consumerMainThread(OpenContainer::handle)
.add();
public static void init() {
@@ -334,7 +334,7 @@ public class SimpleChannel extends Channel<Object> {
@SuppressWarnings("unchecked")
@Override
protected FriendlyByteBuf toBuffer(Object message) {
public FriendlyByteBuf toBuffer(Object message) {
var msg = byType.get(message.getClass());
if (msg == null) {
@@ -10,8 +10,6 @@ import org.jetbrains.annotations.ApiStatus;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.MenuAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
@@ -55,23 +53,20 @@ public class OpenContainer {
@SuppressWarnings("unchecked")
public static void handle(OpenContainer msg, CustomPayloadEvent.Context ctx) {
ctx.enqueueWork(() -> {
try {
var mc = Minecraft.getInstance();
var inv = mc.player.getInventory();
MenuScreens.getScreenFactory(msg.getType(), mc, msg.getWindowId(), msg.getName()).ifPresent(f -> {
AbstractContainerMenu c = msg.getType().create(msg.getWindowId(), inv, msg.getAdditionalData());
try {
var mc = Minecraft.getInstance();
var inv = mc.player.getInventory();
var factory = MenuScreens.getScreenFactory(msg.getType(), mc, msg.getWindowId(), msg.getName());
factory.ifPresent(f -> {
var c = msg.getType().create(msg.getWindowId(), inv, msg.getAdditionalData());
Screen s = ((MenuScreens.ScreenConstructor<AbstractContainerMenu, ?>)f).create(c, inv, msg.getName());
mc.player.containerMenu = ((MenuAccess<?>)s).getMenu();
mc.setScreen(s);
});
} finally {
msg.getAdditionalData().release();
}
});
ctx.setPacketHandled(true);
var s = ((MenuScreens.ScreenConstructor<AbstractContainerMenu, ?>)f).create(c, inv, msg.getName());
mc.player.containerMenu = s.getMenu();
mc.setScreen(s);
});
} finally {
msg.getAdditionalData().release();
}
}
@SuppressWarnings("deprecation")
@@ -8,6 +8,8 @@ package net.minecraftforge.network.packets;
import java.util.Optional;
import java.util.UUID;
import org.jetbrains.annotations.ApiStatus;
import io.netty.buffer.Unpooled;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -30,6 +32,7 @@ import net.minecraftforge.event.network.CustomPayloadEvent;
* {@link EntityType})
* see {@link EntityType.Builder#setCustomClientFactory}.
*/
// TODO: Re-write this packet into something simpler. This is literally just ClientboundAddEntityPacket with an extra byte[]
public class SpawnEntity {
private final Entity entity;
private final int typeId;
@@ -41,7 +44,8 @@ public class SpawnEntity {
private final FriendlyByteBuf buf;
@SuppressWarnings("deprecation")
SpawnEntity(Entity e) {
@ApiStatus.Internal
public SpawnEntity(Entity e) {
this.entity = e;
this.typeId = BuiltInRegistries.ENTITY_TYPE.getId(e.getType()); //TODO: Codecs
this.entityId = e.getId();
@@ -123,36 +127,33 @@ public class SpawnEntity {
}
public static void handle(SpawnEntity msg, CustomPayloadEvent.Context ctx) {
ctx.enqueueWork(() -> {
try {
@SuppressWarnings("deprecation")
EntityType<?> type = BuiltInRegistries.ENTITY_TYPE.byId(msg.typeId);
Optional<Level> world = LogicalSidedProvider.CLIENTWORLD.get(ctx.getDirection().getReceptionSide());
Entity e = world.map(w -> type.customClientSpawn(msg, w)).orElse(null);
if (e == null)
return;
try {
@SuppressWarnings("deprecation")
EntityType<?> type = BuiltInRegistries.ENTITY_TYPE.byId(msg.typeId);
Optional<Level> world = LogicalSidedProvider.CLIENTWORLD.get(ctx.getDirection().getReceptionSide());
Entity e = world.map(w -> type.customClientSpawn(msg, w)).orElse(null);
if (e == null)
return;
/*
* Sets the postiion on the client, Mirrors what
* Entity#recreateFromPacket and LivingEntity#recreateFromPacket does.
*/
e.syncPacketPositionCodec(msg.posX, msg.posY, msg.posZ);
e.absMoveTo(msg.posX, msg.posY, msg.posZ, (msg.yaw * 360) / 256.0F, (msg.pitch * 360) / 256.0F);
e.setYHeadRot((msg.headYaw * 360) / 256.0F);
e.setYBodyRot((msg.headYaw * 360) / 256.0F);
/*
* Sets the postiion on the client, Mirrors what
* Entity#recreateFromPacket and LivingEntity#recreateFromPacket does.
*/
e.syncPacketPositionCodec(msg.posX, msg.posY, msg.posZ);
e.absMoveTo(msg.posX, msg.posY, msg.posZ, (msg.yaw * 360) / 256.0F, (msg.pitch * 360) / 256.0F);
e.setYHeadRot((msg.headYaw * 360) / 256.0F);
e.setYBodyRot((msg.headYaw * 360) / 256.0F);
e.setId(msg.entityId);
e.setUUID(msg.uuid);
if (world.orElse(null) instanceof ClientLevel cworld)
cworld.addEntity(e);
e.lerpMotion(msg.velX / 8000.0, msg.velY / 8000.0, msg.velZ / 8000.0);
if (e instanceof IEntityAdditionalSpawnData entityAdditionalSpawnData)
entityAdditionalSpawnData.readSpawnData(msg.buf);
} finally {
msg.buf.release();
}
});
ctx.setPacketHandled(true);
e.setId(msg.entityId);
e.setUUID(msg.uuid);
if (world.orElse(null) instanceof ClientLevel cworld)
cworld.addEntity(e);
e.lerpMotion(msg.velX / 8000.0, msg.velY / 8000.0, msg.velZ / 8000.0);
if (e instanceof IEntityAdditionalSpawnData entityAdditionalSpawnData)
entityAdditionalSpawnData.readSpawnData(msg.buf);
} finally {
msg.buf.release();
}
}
public Entity getEntity() {