Скользкая тема

ReyMagos

Тег-бомбастер
413
7
131
Наткнулся я как-то на мод, который делает все блоки скользкими, как лёд. Но всё бы ничего, но этот мод работает не только в одиночной игре, но и на серверах. И тут появился вопрос. Пакет о движении игрока формируется на клиенте что ли? Или есть какой спец пакет для скользких блоков? В любом случае посмотрел внутрь мода, а там:
1) Бам
JavaScript:
function initializeCoreMod() {
    return {
        'itemslip': {
            'target': {
                'type': 'METHOD',
                'class': 'net.minecraft.entity.item.ItemEntity',
                'methodName': 'func_70071_h_',
                'methodDesc': '()V'
            },
            'transformer': function(method) {
                var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI');
                var Opcodes = Java.type('org.objectweb.asm.Opcodes');
                var instr = method.instructions;
                var i;
                var owner = "com/turtywurty/slipperymod/SlipperyMod";
                var name = "getMultiplier";
                var desc = "()F";
                var needle;
                for (i = 0; i < instr.size(); i++) {
                    var n = instr.get(i);
                    if (n.getOpcode() == Opcodes.INVOKEVIRTUAL) {
                        var m = n;
                        if (m.name.equals("getSlipperiness")) {
                            needle = m.getNext();
                            break;
                        }
                    }
                }
                if (needle != null) {
                    instr.set(needle, ASMAPI.buildMethodCall(owner, name, desc, ASMAPI.MethodType.STATIC));
                }
                return method;
            }
        }
    }
}
2) Бам
Java:
private void setup(FMLCommonSetupEvent event) {
        Iterator var2 = ForgeRegistries.BLOCKS.iterator();

        while(var2.hasNext()) {
            Block block = (Block)var2.next();
            if (block.getRegistryName().func_110624_b().equals("minecraft")) {
                block.field_149765_K = 1.0934095F;
            }
        }

    }

    public static float getMultiplier() {
        return 0.91F;
    }
То бишь просто замена метода, который возвращает скользкость (коэффицент скольжения, короче) блока. Но как это влияет на движение в мультиплеере - большой вопрос. Самоубийцы Кодеры на 1.16, это фича новых версий? Или это было и раньше и только я этого не знал? В любом случае буду благодарен за любую инфу. В том числе и за фикс.
 
Пакет о движении игрока формируется на клиенте что ли?
Ну... Да. Как, по-твоему, флайхаки-спидхаки работают?

Кодеры на 1.16, это фича новых версий? Или это было и раньше и только я этого не знал?
Давно было. Наверное, всегда.

В том числе и за фикс.
Если у тебя сервер с модами и своим клиентом, то базовую защиту от подкидывания сторонних модов должен обеспечивать лаунчер. Если без модов, то можешь попробовать проверять клиентские моды, которые клиент шлёт при подключении к серверу, но это шаманить надо.
Эта штука не выглядит достаточно читерской, чтобы защищаться конкретно от неё.
 
Движение формируется на клиенте и отправляется на сервер, там оно кое-как проверяется, поэтому такие штуки и работают.
Чтобы такого не было, нужно писать кастомное передвижение, где сервер двигает игрока в зависимости от инпута и после этого сверяет свою позицию с клиентской.
 
Чтобы такого не было, нужно писать кастомное передвижение, где сервер двигает игрока в зависимости от инпута и после этого сверяет свою позицию с клиентской.
Тебе инпутлаг мозг выепит.
Это ведь сделано так не из-за того что моджанги тупые. Если делать как ты говоришь, то уже при 50мс пинга управление будет очень тяжелое и неудобное. Представь: ты нажал кнопку, а на экране игрок передвинулся только через 100мс.
 
Та не, двигать сначала на клиенте, потом отправлять пакет на сервер вместе с инпутом и двигать там.
 
Блин, вообще система проверки сервером после того, когда клиент уже всё сделал такая убогая (на мой неопытный взгляд). Особенно спам этими сообщениями в консоль Player moves too quickly! и дёрганье игрока при падении или просто при быстром беге.
где сервер двигает игрока в зависимости от инпута и после этого сверяет свою позицию с клиентской
На самом деле, такая идея и была.
Тебе инпутлаг мозг выепит.
Но ведь сервер отправляет клиенту позиции игроков, находящиеся в зоне видимости игрока и всё нормально, ничего не висит. Даже если игроков пару десятков.
не выглядит достаточно читерской
Но всё же.
Ничего, пошаманю, если надо будет)
 
Не совсем так, серверу ваще плевать на инпут и он грубо проверяет позицию игрока, не двигая его тем же алгоритмом, что и клиент.
Как пакет передвижения отправляется с клиента:
Java:
public void sendMotionUpdates() {
        boolean flag = this.isSprinting();
        if (flag != this.wasSprinting) {
            if (flag) {
                this.sendQueue.addToSendQueue(new C0BPacketEntityAction(this, 4));
            } else {
                this.sendQueue.addToSendQueue(new C0BPacketEntityAction(this, 5));
            }

            this.wasSprinting = flag;
        }

        boolean flag1 = this.isSneaking();
        if (flag1 != this.wasSneaking) {
            if (flag1) {
                this.sendQueue.addToSendQueue(new C0BPacketEntityAction(this, 1));
            } else {
                this.sendQueue.addToSendQueue(new C0BPacketEntityAction(this, 2));
            }

            this.wasSneaking = flag1;
        }

        double d0 = super.posX - this.oldPosX;
        double d1 = super.boundingBox.minY - this.oldMinY;
        double d2 = super.posZ - this.oldPosZ;
        double d3 = (double)(super.rotationYaw - this.oldRotationYaw);
        double d4 = (double)(super.rotationPitch - this.oldRotationPitch);
        boolean flag2 = d0 * d0 + d1 * d1 + d2 * d2 > 9.0E-4D || this.ticksSinceMovePacket >= 20;
        boolean flag3 = d3 != 0.0D || d4 != 0.0D;
        if (super.ridingEntity != null) {
            this.sendQueue.addToSendQueue(new C06PacketPlayerPosLook(super.motionX, -999.0D, -999.0D, super.motionZ, super.rotationYaw, super.rotationPitch, super.onGround));
            flag2 = false;
        } else if (flag2 && flag3) {
            this.sendQueue.addToSendQueue(new C06PacketPlayerPosLook(super.posX, super.boundingBox.minY, super.posY, super.posZ, super.rotationYaw, super.rotationPitch, super.onGround));
        } else if (flag2) {
            this.sendQueue.addToSendQueue(new C04PacketPlayerPosition(super.posX, super.boundingBox.minY, super.posY, super.posZ, super.onGround));
        } else if (flag3) {
            this.sendQueue.addToSendQueue(new C05PacketPlayerLook(super.rotationYaw, super.rotationPitch, super.onGround));
        } else {
            this.sendQueue.addToSendQueue(new C03PacketPlayer(super.onGround));
        }

        ++this.ticksSinceMovePacket;
        this.wasOnGround = super.onGround;
        if (flag2) {
            this.oldPosX = super.posX;
            this.oldMinY = super.boundingBox.minY;
            this.oldPosY = super.posY;
            this.oldPosZ = super.posZ;
            this.ticksSinceMovePacket = 0;
        }

        if (flag3) {
            this.oldRotationYaw = super.rotationYaw;
            this.oldRotationPitch = super.rotationPitch;
        }

    }
Инпут отправляется отдельным пакетом и не используется для проверки передвижения

Обработка инпута:
Java:
public void processInput(C0CPacketInput p_147358_1_) {
        this.playerEntity.setEntityActionState(p_147358_1_.func_149620_c(), p_147358_1_.func_149616_d(), p_147358_1_.func_149618_e(), p_147358_1_.func_149617_f());

public void setEntityActionState(float p_110430_1_, float p_110430_2_, boolean p_110430_3_, boolean p_110430_4_)
{
    if (this.ridingEntity != null)
    {
        if (p_110430_1_ >= -1.0F && p_110430_1_ <= 1.0F)
        {
            this.moveStrafing = p_110430_1_;
        }

        if (p_110430_2_ >= -1.0F && p_110430_2_ <= 1.0F)
        {
            this.moveForward = p_110430_2_;
        }

        this.isJumping = p_110430_3_;
        this.setSneaking(p_110430_4_);
    }
}
    }
 
Ну по факту сервер вообще ничего не проверяет, только записывает данные с клиента. Если я правильно понимаю код обработки пакета.
 
Он проверяет скорость передвижения и делает рейкаст между текущей и следующей позицией, чтобы нельзя было ходить сквозь стены.
Но ведь сервер отправляет клиенту позиции игроков, находящиеся в зоне видимости игрока и всё нормально, ничего не висит. Даже если игроков пару десятков.
Причем тут другие игроки вообще? Я тебе объяснил в чем смысл такого решения. И да, это не только в майне так, а почти во всех более-менее динамичных играх.
 
Назад
Сверху