Синхронизация позиции entity [1.7.10]

2,502
78
380
Причем тут стрела? В ней куча приватного шлака, которым нельзя пользоваться. Поэтому я ее переписал под себя.
 
608
5
15
Dahaka написал(а):
Причем тут стрела? В ней куча приватного шлака, которым нельзя пользоваться. Поэтому я ее переписал под себя.
Ты решил проблему? Даёшь хуки?
 
2,502
78
380
Еще в процессе. Времени не было
 
2,502
78
380
Проблема решена.

Самым проблемным местом оказался конструктор пакета S12PacketEntityVelocity.
Код:
public S12PacketEntityVelocity(int p_i45220_1_, double p_i45220_2_, double p_i45220_4_, double p_i45220_6_)
{
    this.field_149417_a = p_i45220_1_;
    double d3 = 3.9D;

    if (p_i45220_2_ < -d3)
    {
        p_i45220_2_ = -d3;
    }

    if (p_i45220_4_ < -d3)
    {
        p_i45220_4_ = -d3;
    }

    if (p_i45220_6_ < -d3)
    {
        p_i45220_6_ = -d3;
    }

    if (p_i45220_2_ > d3)
    {
        p_i45220_2_ = d3;
    }

    if (p_i45220_4_ > d3)
    {
        p_i45220_4_ = d3;
    }

    if (p_i45220_6_ > d3)
    {
        p_i45220_6_ = d3;
    }

    this.field_149415_b = (int)(p_i45220_2_ * 8000.0D);
    this.field_149416_c = (int)(p_i45220_4_ * 8000.0D);
    this.field_149414_d = (int)(p_i45220_6_ * 8000.0D);
}

Беда в том, что я не смог вставить хук в начала конструктора, а можанги настолько гениальны, что модифицируют входные параметры, и реальные значения motion теряются. Поэтому пришлось вставить хуки во все методы, где создается этот пакет. Эти хуки полная замена стандартных методов, за исключением моих правок.

Итоговый класс с хуками. Надеюсь, вы знаете, что с ним делать.
Код:
/**
 * Fix incorrect motion setting for {@link Entity}.
 */
public class FixIncorrectMotionHooks
{
    /**
     * Fix incorrect motion setting for {@link IThrowableEntity}, when it spawned.
     */
    @Hook(returnCondition = ReturnCondition.ALWAYS)
    public static void toBytes(FMLMessage.EntitySpawnMessage message, ByteBuf buf)
    {
        Entity entity = ReflectionHelper.getPrivateValue(FMLMessage.EntityMessage.class, message, "entity");

        String modId = ReflectionHelper.getPrivateValue(FMLMessage.EntitySpawnMessage.class, message, "modId");
        int modEntityTypeId = ReflectionHelper.getPrivateValue(FMLMessage.EntitySpawnMessage.class, message, "modEntityTypeId");

        // T0D0: super method
        buf.writeInt(entity.getEntityId());

        // T0D0: this method
        ByteBufUtils.writeUTF8String(buf, modId);
        buf.writeInt(modEntityTypeId);

        buf.writeInt(MathHelper.floor_double(entity.posX * 32D));
        buf.writeInt(MathHelper.floor_double(entity.posY * 32D));
        buf.writeInt(MathHelper.floor_double(entity.posZ * 32D));

        buf.writeByte((byte)(entity.rotationYaw * 256.0F / 360.0F));
        buf.writeByte((byte) (entity.rotationPitch * 256.0F / 360.0F));

        if (entity instanceof EntityLivingBase) {
            buf.writeByte((byte) (((EntityLivingBase)entity).rotationYawHead * 256.0F / 360.0F));
        }
        else {
            buf.writeByte(0);
        }

        ByteBuf tmpBuf = Unpooled.buffer();
        PacketBuffer pb = new PacketBuffer(tmpBuf);

        try {
            entity.getDataWatcher().func_151509_a(pb);
        }
        catch (IOException e) {
            FMLLog.log(Level.FATAL,e,"Encountered fatal exception trying to send entity spawn data watchers");
            throw Throwables.propagate(e);
        }
        buf.writeBytes(tmpBuf);

        if (entity instanceof IThrowableEntity) {
            Entity owner = ((IThrowableEntity)entity).getThrower();
            buf.writeInt(owner == null ? entity.getEntityId() : owner.getEntityId());
            // T0D0: fix
            buf.writeInt((int) (entity.motionX * 8000D));
            buf.writeInt((int) (entity.motionY * 8000D));
            buf.writeInt((int) (entity.motionZ * 8000D));
        }
        else {
            buf.writeInt(0);
        }

        if (entity instanceof IEntityAdditionalSpawnData) {
            tmpBuf = Unpooled.buffer();
            ((IEntityAdditionalSpawnData)entity).writeSpawnData(tmpBuf);
            buf.writeBytes(tmpBuf);
        }
    }

    /**
     * Fix incorrect setting for the motion {@link Entity}, when it moves
     */
    @Hook(returnCondition = ReturnCondition.ALWAYS)
    public static void sendLocationToAllClients(EntityTrackerEntry tracker, List list)
    {
        tracker.playerEntitiesUpdated = false;

        if (!tracker.isDataInitialized ||
            tracker.myEntity.getDistanceSq(tracker.posX, tracker.posY, tracker.posZ) > 16.0D) {
            tracker.posX = tracker.myEntity.posX;
            tracker.posY = tracker.myEntity.posY;
            tracker.posZ = tracker.myEntity.posZ;
            tracker.isDataInitialized = true;
            tracker.playerEntitiesUpdated = true;
            tracker.sendEventsToPlayers(list);
        }

        if (tracker.field_85178_v != tracker.myEntity.ridingEntity ||
            tracker.myEntity.ridingEntity != null && tracker.ticks % 60 == 0) {
            tracker.field_85178_v = tracker.myEntity.ridingEntity;
            tracker.func_151259_a(new S1BPacketEntityAttach(0, tracker.myEntity, tracker.myEntity.ridingEntity));
        }

        if (tracker.myEntity instanceof EntityItemFrame && tracker.ticks % 10 == 0) {
            EntityItemFrame entityitemframe = (EntityItemFrame) tracker.myEntity;
            ItemStack stack = entityitemframe.getDisplayedItem();

            if (stack != null && stack.getItem() instanceof ItemMap) {
                MapData mapdata = Items.filled_map.getMapData(stack, tracker.myEntity.worldObj);
                for (Object obj : list) {
                    EntityPlayerMP player = (EntityPlayerMP) obj;
                    mapdata.updateVisiblePlayers(player, stack);
                    Packet packet = Items.filled_map.func_150911_c(stack, tracker.myEntity.worldObj, player);

                    if (packet != null) {
                        player.playerNetServerHandler.sendPacket(packet);
                    }
                }
            }
            tracker.sendMetadataToAllAssociatedPlayers();
        }
        else if (tracker.ticks % tracker.updateFrequency == 0 ||
                 tracker.myEntity.isAirBorne || tracker.myEntity.getDataWatcher().hasChanges()) {
            int i;
            int j;

            if (tracker.myEntity.ridingEntity == null) {
                ++tracker.ticksSinceLastForcedTeleport;
                i = tracker.myEntity.myEntitySize.multiplyBy32AndRound(tracker.myEntity.posX);
                j = MathHelper.floor_double(tracker.myEntity.posY * 32.0D);
                int k = tracker.myEntity.myEntitySize.multiplyBy32AndRound(tracker.myEntity.posZ);
                int l = MathHelper.floor_float(tracker.myEntity.rotationYaw * 256.0F / 360.0F);
                int i1 = MathHelper.floor_float(tracker.myEntity.rotationPitch * 256.0F / 360.0F);
                int j1 = i - tracker.lastScaledXPosition;
                int k1 = j - tracker.lastScaledYPosition;
                int l1 = k - tracker.lastScaledZPosition;
                Object object = null;
                boolean flag = Math.abs(j1) >= 4 || Math.abs(k1) >= 4 || Math.abs(l1) >= 4 || tracker.ticks % 60 == 0;
                boolean flag1 = Math.abs(l - tracker.lastYaw) >= 4 || Math.abs(i1 - tracker.lastPitch) >= 4;

                if (tracker.ticks > 0 || tracker.myEntity instanceof EntityArrow) {
                    if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 &&
                        l1 < 128 && tracker.ticksSinceLastForcedTeleport <= 400 && !tracker.ridingEntity) {
                        if (flag && flag1) {
                            object = new S14PacketEntity.S17PacketEntityLookMove(tracker.myEntity.getEntityId(),
                                                                                (byte)j1, (byte)k1, (byte)l1, (byte)l, (byte)i1);
                        }
                        else if (flag) {
                            object = new S14PacketEntity.S15PacketEntityRelMove(tracker.myEntity.getEntityId(),
                                                                                (byte)j1, (byte)k1, (byte)l1);
                        }
                        else if (flag1) {
                            object = new S14PacketEntity.S16PacketEntityLook(tracker.myEntity.getEntityId(), (byte)l, (byte)i1);
                        }
                    }
                    else {
                        tracker.ticksSinceLastForcedTeleport = 0;
                        object = new S18PacketEntityTeleport(tracker.myEntity.getEntityId(), i, j, k, (byte)l, (byte)i1);
                    }
                }

                if (tracker.sendVelocityUpdates) {
                    double d0 = tracker.myEntity.motionX - tracker.motionX;
                    double d1 = tracker.myEntity.motionY - tracker.motionY;
                    double d2 = tracker.myEntity.motionZ - tracker.motionZ;
                    double d3 = 0.02D;
                    double d4 = d0 * d0 + d1 * d1 + d2 * d2;

                    if (d4 > d3 * d3 || d4 > 0.0D && tracker.myEntity.motionX == 0.0D &&
                        tracker.myEntity.motionY == 0.0D && tracker.myEntity.motionZ == 0.0D) {
                        tracker.motionX = tracker.myEntity.motionX;
                        tracker.motionY = tracker.myEntity.motionY;
                        tracker.motionZ = tracker.myEntity.motionZ;
                        // T0D0: fix
                        tracker.func_151259_a(createVelocityPacket(tracker.myEntity.getEntityId(), tracker.motionX,
                                                                   tracker.motionY, tracker.motionZ));
                    }
                }

                if (object != null) {
                    tracker.func_151259_a((Packet)object);
                }

                tracker.sendMetadataToAllAssociatedPlayers();

                if (flag) {
                    tracker.lastScaledXPosition = i;
                    tracker.lastScaledYPosition = j;
                    tracker.lastScaledZPosition = k;
                }

                if (flag1) {
                    tracker.lastYaw = l;
                    tracker.lastPitch = i1;
                }

                tracker.ridingEntity = false;
            }
            else {
                i = MathHelper.floor_float(tracker.myEntity.rotationYaw * 256.0F / 360.0F);
                j = MathHelper.floor_float(tracker.myEntity.rotationPitch * 256.0F / 360.0F);
                boolean flag2 = Math.abs(i - tracker.lastYaw) >= 4 || Math.abs(j - tracker.lastPitch) >= 4;

                if (flag2) {
                    tracker.func_151259_a(new S14PacketEntity.S16PacketEntityLook(tracker.myEntity.getEntityId(), (byte)i, (byte)j));
                    tracker.lastYaw = i;
                    tracker.lastPitch = j;
                }

                tracker.lastScaledXPosition = tracker.myEntity.myEntitySize.multiplyBy32AndRound(tracker.myEntity.posX);
                tracker.lastScaledYPosition = MathHelper.floor_double(tracker.myEntity.posY * 32.0D);
                tracker.lastScaledZPosition = tracker.myEntity.myEntitySize.multiplyBy32AndRound(tracker.myEntity.posZ);
                tracker.sendMetadataToAllAssociatedPlayers();
                tracker.ridingEntity = true;
            }

            i = MathHelper.floor_float(tracker.myEntity.getRotationYawHead() * 256.0F / 360.0F);

            if (Math.abs(i - tracker.lastHeadMotion) >= 4) {
                tracker.func_151259_a(new S19PacketEntityHeadLook(tracker.myEntity, (byte)i));
                tracker.lastHeadMotion = i;
            }

            tracker.myEntity.isAirBorne = false;
        }

        ++tracker.ticks;

        if (tracker.myEntity.velocityChanged) {
            // T0D0: fix
            tracker.func_151261_b(createVelocityPacket(tracker.myEntity.getEntityId(), tracker.myEntity.motionX,
                                                       tracker.myEntity.motionY, tracker.myEntity.motionZ));
            tracker.myEntity.velocityChanged = false;
        }
    }

    /**
     * Fix incorrect setting for the motion {@link Entity}, when it moves
     */
    @Hook(returnCondition = ReturnCondition.ALWAYS)
    public static void tryStartWachingThis(EntityTrackerEntry tracker, EntityPlayerMP player)
    {
        if (player != tracker.myEntity) {
            double d0 = player.posX - tracker.lastScaledXPosition / 32;
            double d1 = player.posZ - tracker.lastScaledZPosition / 32;

            if (d0 >= (-tracker.blocksDistanceThreshold) && d0 <= tracker.blocksDistanceThreshold &&
                d1 >= (-tracker.blocksDistanceThreshold) && d1 <= tracker.blocksDistanceThreshold) {
                if (!tracker.trackingPlayers.contains(player) && (tracker.isPlayerWatchingThisChunk(player) ||
                                                                  tracker.myEntity.forceSpawn)) {
                    tracker.trackingPlayers.add(player);
                    Packet packet = tracker.func_151260_c();
                    player.playerNetServerHandler.sendPacket(packet);

                    if (!tracker.myEntity.getDataWatcher().getIsBlank()) {
                        player.playerNetServerHandler.sendPacket(new S1CPacketEntityMetadata(tracker.myEntity.getEntityId(),
                                                                                             tracker.myEntity.getDataWatcher(), true));
                    }

                    if (tracker.myEntity instanceof EntityLivingBase) {
                        ServersideAttributeMap map = (ServersideAttributeMap)((EntityLivingBase)tracker.myEntity).getAttributeMap();
                        Collection collection = map.getWatchedAttributes();

                        if (!collection.isEmpty()) {
                            player.playerNetServerHandler.sendPacket(new S20PacketEntityProperties(tracker.myEntity.getEntityId(), collection));
                        }
                    }

                    tracker.motionX = tracker.myEntity.motionX;
                    tracker.motionY = tracker.myEntity.motionY;
                    tracker.motionZ = tracker.myEntity.motionZ;

                    int posX = MathHelper.floor_double(tracker.myEntity.posX * 32.0D);
                    int posY = MathHelper.floor_double(tracker.myEntity.posY * 32.0D);
                    int posZ = MathHelper.floor_double(tracker.myEntity.posZ * 32.0D);
                    if (posX != tracker.lastScaledXPosition || posY != tracker.lastScaledYPosition || posZ != tracker.lastScaledZPosition) {
                        FMLNetworkHandler.makeEntitySpawnAdjustment(tracker.myEntity, player, tracker.lastScaledXPosition,
                                                                    tracker.lastScaledYPosition, tracker.lastScaledZPosition);
                    }

                    if (tracker.sendVelocityUpdates && !(packet instanceof S0FPacketSpawnMob)) {
                        // T0D0: fix
                        player.playerNetServerHandler.sendPacket(createVelocityPacket(tracker.myEntity.getEntityId(), tracker.myEntity.motionX,
                                                                                      tracker.myEntity.motionY, tracker.myEntity.motionZ));
                    }

                    if (tracker.myEntity.ridingEntity != null) {
                        player.playerNetServerHandler.sendPacket(new S1BPacketEntityAttach(0, tracker.myEntity, tracker.myEntity.ridingEntity));
                    }

                    if (tracker.myEntity instanceof EntityLiving && ((EntityLiving)tracker.myEntity).getLeashedToEntity() != null) {
                        player.playerNetServerHandler.sendPacket(new S1BPacketEntityAttach(1, tracker.myEntity, ((EntityLiving)tracker.myEntity).getLeashedToEntity()));
                    }

                    if (tracker.myEntity instanceof EntityLivingBase) {
                        for (int i = 0; i < 5; ++i) {
                            ItemStack stack = ((EntityLivingBase)tracker.myEntity).getEquipmentInSlot(i);

                            if (stack != null) {
                                player.playerNetServerHandler.sendPacket(new S04PacketEntityEquipment(tracker.myEntity.getEntityId(), i, stack));
                            }
                        }
                    }

                    if (tracker.myEntity instanceof EntityPlayer) {
                        EntityPlayer entityplayer = (EntityPlayer)tracker.myEntity;

                        if (entityplayer.isPlayerSleeping()) {
                            player.playerNetServerHandler.sendPacket(new S0APacketUseBed(entityplayer, MathHelper.floor_double(tracker.myEntity.posX),
                                                                                                       MathHelper.floor_double(tracker.myEntity.posY),
                                                                                                       MathHelper.floor_double(tracker.myEntity.posZ)));
                        }
                    }

                    if (tracker.myEntity instanceof EntityLivingBase) {
                        EntityLivingBase entitylivingbase = (EntityLivingBase)tracker.myEntity;
                        Iterator iterator = entitylivingbase.getActivePotionEffects().iterator();

                        while (iterator.hasNext()) {
                            PotionEffect potioneffect = (PotionEffect)iterator.next();
                            player.playerNetServerHandler.sendPacket(new S1DPacketEntityEffect(tracker.myEntity.getEntityId(), potioneffect));
                        }
                    }
                    net.minecraftforge.event.ForgeEventFactory.onStartEntityTracking(tracker.myEntity, player);
                }
            }
            else if (tracker.trackingPlayers.contains(player)) {
                tracker.trackingPlayers.remove(player);
                player.func_152339_d(tracker.myEntity);
                net.minecraftforge.event.ForgeEventFactory.onStopEntityTracking(tracker.myEntity, player);
            }
        }
    }

    /**
     *  Create normal {@link S12PacketEntityVelocity}
     */
    private static S12PacketEntityVelocity createVelocityPacket(int entityId, double motionX, double motionY, double motionZ)
    {
        S12PacketEntityVelocity packet = new S12PacketEntityVelocity();
        packet.field_149417_a = entityId;
        packet.field_149415_b = (int) (motionX * 8000.0D);
        packet.field_149416_c = (int) (motionY * 8000.0D);
        packet.field_149414_d = (int) (motionZ * 8000.0D);
        return packet;
    }
}
[merge_posts_bbcode]Добавлено: 19.07.2016 01:09:54[/merge_posts_bbcode]

А, совсем забыл, нужно в классах EntityTrackerEntry и S12PacketEntityVelocity сделать все поля данных публичными. А в классе EntityTrackerEntry и методы.

[merge_posts_bbcode]Добавлено: 19.07.2016 01:11:32[/merge_posts_bbcode]

Если кто-то сможет сказать мне, как в классе FMLMessage.EntitySpawnMessage сделать все поля публичными, я буду рад. А то у меня через АТ не вышло.

[merge_posts_bbcode]Добавлено: 19.07.2016 01:13:34[/merge_posts_bbcode]

А если кто-то умеет вставлять хук в начало конструктора, то будет совсем шикарно.
 
6,095
226
1,174
Для получения доступа к любому полю - рефлексия, но будет хреново, если она будет юзаться каждый тик
 
2,502
78
380
Спасибо, конечно, но мне итак приходится ее юзать. Мне нужен другой способ.
 
1,137
5
2
А че хук вставлять? Конструктор - "метод" с именем <init>
 
2,502
78
380
В конец вставляется, в начало нет
 
Сверху