mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 16:27:47 +00:00
Fix Forge's packet handling on play messages. (#8875)
This commit is contained in:
1 parent
18f5bdb7ca
commit
d988b4a811
1 file changed
+88
-64
@@ -7,26 +7,24 @@ package net.minecraftforge.network;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.inventory.MenuAccess;
|
||||
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.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.common.util.LogicalSidedProvider;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraftforge.entity.IEntityAdditionalSpawnData;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
@@ -36,8 +34,9 @@ public class PlayMessages
|
||||
/**
|
||||
* Used to spawn a custom entity without the same restrictions as
|
||||
* {@link ClientboundAddEntityPacket}
|
||||
*
|
||||
* To customize how your entity is created clientside (instead of using the default factory provided to the {@link EntityType})
|
||||
* <p>
|
||||
* To customize how your entity is created clientside (instead of using the default factory provided to the
|
||||
* {@link EntityType})
|
||||
* see {@link EntityType.Builder#setCustomClientFactory}.
|
||||
*/
|
||||
public static class SpawnEntity
|
||||
@@ -67,14 +66,13 @@ public class PlayMessages
|
||||
double d1 = Mth.clamp(vec3d.x, -3.9D, 3.9D);
|
||||
double d2 = Mth.clamp(vec3d.y, -3.9D, 3.9D);
|
||||
double d3 = Mth.clamp(vec3d.z, -3.9D, 3.9D);
|
||||
this.velX = (int)(d1 * 8000.0D);
|
||||
this.velY = (int)(d2 * 8000.0D);
|
||||
this.velZ = (int)(d3 * 8000.0D);
|
||||
this.velX = (int) (d1 * 8000.0D);
|
||||
this.velY = (int) (d2 * 8000.0D);
|
||||
this.velZ = (int) (d3 * 8000.0D);
|
||||
this.buf = null;
|
||||
}
|
||||
|
||||
private SpawnEntity(int typeId, int entityId, UUID uuid, double posX, double posY, double posZ,
|
||||
byte pitch, byte yaw, byte headYaw, int velX, int velY, int velZ, FriendlyByteBuf buf)
|
||||
private SpawnEntity(int typeId, int entityId, UUID uuid, double posX, double posY, double posZ, byte pitch, byte yaw, byte headYaw, int velX, int velY, int velZ, FriendlyByteBuf buf)
|
||||
{
|
||||
this.entity = null;
|
||||
this.typeId = typeId;
|
||||
@@ -107,57 +105,73 @@ public class PlayMessages
|
||||
buf.writeShort(msg.velX);
|
||||
buf.writeShort(msg.velY);
|
||||
buf.writeShort(msg.velZ);
|
||||
if (msg.entity instanceof IEntityAdditionalSpawnData)
|
||||
if (msg.entity instanceof IEntityAdditionalSpawnData entityAdditionalSpawnData)
|
||||
{
|
||||
((IEntityAdditionalSpawnData) msg.entity).writeSpawnData(buf);
|
||||
final FriendlyByteBuf spawnDataBuffer = new FriendlyByteBuf(Unpooled.buffer());
|
||||
|
||||
entityAdditionalSpawnData.writeSpawnData(spawnDataBuffer);
|
||||
|
||||
buf.writeVarInt(spawnDataBuffer.readableBytes());
|
||||
buf.writeBytes(spawnDataBuffer);
|
||||
|
||||
spawnDataBuffer.release();
|
||||
} else
|
||||
{
|
||||
buf.writeVarInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static SpawnEntity decode(FriendlyByteBuf buf)
|
||||
{
|
||||
return new SpawnEntity(
|
||||
buf.readVarInt(),
|
||||
buf.readInt(),
|
||||
new UUID(buf.readLong(), buf.readLong()),
|
||||
buf.readDouble(), buf.readDouble(), buf.readDouble(),
|
||||
buf.readByte(), buf.readByte(), buf.readByte(),
|
||||
buf.readShort(), buf.readShort(), buf.readShort(),
|
||||
buf
|
||||
);
|
||||
return new SpawnEntity(buf.readVarInt(), buf.readInt(), new UUID(buf.readLong(), buf.readLong()), buf.readDouble(), buf.readDouble(), buf.readDouble(), buf.readByte(), buf.readByte(), buf.readByte(), buf.readShort(), buf.readShort(), buf.readShort(), readSpawnDataPacket(buf));
|
||||
}
|
||||
|
||||
private static FriendlyByteBuf readSpawnDataPacket(FriendlyByteBuf buf)
|
||||
{
|
||||
final int count = buf.readVarInt();
|
||||
if (count > 0)
|
||||
{
|
||||
final FriendlyByteBuf spawnDataBuffer = new FriendlyByteBuf(Unpooled.buffer());
|
||||
spawnDataBuffer.writeBytes(buf, count);
|
||||
return spawnDataBuffer;
|
||||
}
|
||||
|
||||
return new FriendlyByteBuf(Unpooled.buffer());
|
||||
}
|
||||
|
||||
public static void handle(SpawnEntity msg, Supplier<NetworkEvent.Context> ctx)
|
||||
{
|
||||
ctx.get().enqueueWork(() -> {
|
||||
EntityType<?> type = Registry.ENTITY_TYPE.byId(msg.typeId);
|
||||
if (type == null)
|
||||
try
|
||||
{
|
||||
throw new RuntimeException(String.format(Locale.ENGLISH, "Could not spawn entity (id %d) with unknown type at (%f, %f, %f)", msg.entityId, msg.posX, msg.posY, msg.posZ));
|
||||
}
|
||||
EntityType<?> type = Registry.ENTITY_TYPE.byId(msg.typeId);
|
||||
Optional<Level> world = LogicalSidedProvider.CLIENTWORLD.get(ctx.get().getDirection().getReceptionSide());
|
||||
Entity e = world.map(w -> type.customClientSpawn(msg, w)).orElse(null);
|
||||
if (e == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Level> world = LogicalSidedProvider.CLIENTWORLD.get(ctx.get().getDirection().getReceptionSide());
|
||||
Entity e = world.map(w->type.customClientSpawn(msg, w)).orElse(null);
|
||||
if (e == null)
|
||||
/*
|
||||
* 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);
|
||||
world.filter(ClientLevel.class::isInstance).ifPresent(w -> ((ClientLevel) w).putNonPlayerEntity(msg.entityId, 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
|
||||
{
|
||||
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);
|
||||
|
||||
e.setId(msg.entityId);
|
||||
e.setUUID(msg.uuid);
|
||||
world.filter(ClientLevel.class::isInstance).ifPresent(w->((ClientLevel)w).putNonPlayerEntity(msg.entityId, e));
|
||||
e.lerpMotion(msg.velX / 8000.0, msg.velY / 8000.0, msg.velZ / 8000.0);
|
||||
if (e instanceof IEntityAdditionalSpawnData)
|
||||
{
|
||||
((IEntityAdditionalSpawnData) e).readSpawnData(msg.buf);
|
||||
msg.buf.release();
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
@@ -270,31 +284,41 @@ public class PlayMessages
|
||||
public static void handle(OpenContainer msg, Supplier<NetworkEvent.Context> ctx)
|
||||
{
|
||||
ctx.get().enqueueWork(() -> {
|
||||
MenuScreens.getScreenFactory(msg.getType(), Minecraft.getInstance(), msg.getWindowId(), msg.getName())
|
||||
.ifPresent(f -> {
|
||||
AbstractContainerMenu c = msg.getType().create(msg.getWindowId(), Minecraft.getInstance().player.getInventory(), msg.getAdditionalData());
|
||||
@SuppressWarnings("unchecked")
|
||||
Screen s = ((MenuScreens.ScreenConstructor<AbstractContainerMenu, ?>)f).create(c, Minecraft.getInstance().player.getInventory(), msg.getName());
|
||||
Minecraft.getInstance().player.containerMenu = ((MenuAccess<?>)s).getMenu();
|
||||
Minecraft.getInstance().setScreen(s);
|
||||
});
|
||||
try
|
||||
{
|
||||
MenuScreens.getScreenFactory(msg.getType(), Minecraft.getInstance(), msg.getWindowId(), msg.getName()).ifPresent(f -> {
|
||||
AbstractContainerMenu c = msg.getType().create(msg.getWindowId(), Minecraft.getInstance().player.getInventory(), msg.getAdditionalData());
|
||||
|
||||
@SuppressWarnings("unchecked") Screen s = ((MenuScreens.ScreenConstructor<AbstractContainerMenu, ?>) f).create(c, Minecraft.getInstance().player.getInventory(), msg.getName());
|
||||
Minecraft.getInstance().player.containerMenu = ((MenuAccess<?>) s).getMenu();
|
||||
Minecraft.getInstance().setScreen(s);
|
||||
});
|
||||
} finally
|
||||
{
|
||||
msg.getAdditionalData().release();
|
||||
}
|
||||
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
|
||||
public final MenuType<?> getType() {
|
||||
public final MenuType<?> getType()
|
||||
{
|
||||
return Registry.MENU.byId(this.id);
|
||||
}
|
||||
|
||||
public int getWindowId() {
|
||||
public int getWindowId()
|
||||
{
|
||||
return windowId;
|
||||
}
|
||||
|
||||
public Component getName() {
|
||||
public Component getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public FriendlyByteBuf getAdditionalData() {
|
||||
public FriendlyByteBuf getAdditionalData()
|
||||
{
|
||||
return additionalData;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user