Перейти к публикации

Гайд как пофиксить опавший бетон в лобби MG


Рекомендованные сообщения

UPD: решили все же чинить баг на самом серверном ядре, так как это априори правильнее, но можно почитать и мои танцы в клиенте

 

Краткий ввод, почему вообще происходит такой визуальный баг: когда сервер заменяет где-либо блок с одного типа на другой, он проверяет, нет ли у этого блока гравитации, и если есть, то начинает спавнить EntityFallingBlock, который мы знаем в простонародье как "падающий блок". Конечно, в Spigot есть возможность менять блоки без применения физики, оно и понятно, ведь на самом деле блок никуда не пропадает, а остается на своем месте, просто визуально для игрока он пропадает, и мы скоро узнаем почему

Я считаю, что фикс должен быть немного другим. Действительно сложно постоянно стрелять по бетону, чтобы он не падал. Поэтому я решил обратиться к коду клиента и сервера Minecraft. Буду честен, копался довольно продолжительное время, дебажил все процессы, которые происходят и не происходят.

И наконец - удалось найти косяк! Дело в том, что оригинальный код подразумевает удаление блока в том месте, где появляется сущность падающего блока. Другой вопрос, что такой код на самом деле дублируется - на стороне сервера и на стороне клиента.

Быть кодером необязательно, чтобы понять, что делают эти отрывки кода, и понять, что они повторяют друг друга

// Код с клиента Minecraft
if (this.fallTime++ == 0) {
    BlockPos blockpos = new BlockPos(this);
    
    if (this.worldObj.getBlockState(blockpos).getBlock() == block) {
        this.worldObj.setBlockToAir(blockpos);
    } else if (!this.worldObj.isRemote) {
        this.setDead();
        return;
    }
}
// Код с сервера Spigot
BlockPosition blockposition;
if (this.ticksLived++ == 0) {
    blockposition = new BlockPosition(this);
    if (this.world.getType(blockposition).getBlock() == block && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition.getX(), blockposition.getY(), blockposition.getZ(), Blocks.AIR, 0).isCancelled()) {
        this.world.setAir(blockposition);
        this.world.spigotConfig.antiXrayInstance.updateNearbyBlocks(this.world, blockposition);
    } else if (!this.world.isClientSide) {
        this.die();
        return;
    }
}

Но одно отличие все же есть - второй код не будет вызван при замене блока на падающий. Да, во время выключенной физики выполняется только второй блок с условиями, где этот блок просто "умирает". В следующие моменты в любом случае падающий блок появится и удалит блок, на котором он был, соответственно клиенту необязательно сразу же удалять появившийся у него падающий блок (на самом деле там было еще много процессов, в том числе отправка пакета на создание такого блока), потому что еще не факт, что он действительно будет падать после отмены ивентов физики.

Делаем совсем немножечко изменений и получаем возможно не очень красивый результат, ведь все же на микромомент падающий блок успевает появиться на клиенте из-за получения пакета от сервера, но тут я бессилен, ядро редактировать у меня нет возможностей.

if (this.fallTime++ == 0) {
    // VimeWorld start
    // BlockPos blockpos = new BlockPos(this);
    // if (this.worldObj.getBlockState(blockpos).getBlock() == block) {
    //     this.worldObj.setBlockToAir(blockpos);
    // } else
    // VimeWorld end
    if (!this.worldObj.isRemote) {
        this.setDead();
        return;
    }
}

Забавный факт, что помимо исправления визуального бага с сыпучими блоками, исчезает и надоедливый баг, когда невозможно спамить такими блоками, например при строительстве на BuildBattle

Скрытый текст

До: 

После:

 

 

Ссылка на комментарий
18 минут назад, iKpudka сказал:

Краткий ввод, почему вообще происходит такой визуальный баг: когда сервер заменяет где-либо блок с одного типа на другой, он проверяет, нет ли у этого блока гравитации, и если есть, то начинает спавнить EntityFallingBlock, который мы знаем в простонародье как "падающий блок". Конечно, в Spigot есть возможность менять блоки без применения физики, оно и понятно, ведь на самом деле блок никуда не пропадает, а остается на своем месте, просто визуально для игрока он пропадает, и мы скоро узнаем почему

Я считаю, что фикс должен быть немного другим. Действительно сложно постоянно стрелять по бетону, чтобы он не падал. Поэтому я решил обратиться к коду клиента и сервера Minecraft. Буду честен, копался довольно продолжительное время, дебажил все процессы, которые происходят и не происходят.

И наконец - удалось найти косяк! Дело в том, что оригинальный код подразумевает удаление блока в том месте, где появляется сущность падающего блока. Другой вопрос, что такой код на самом деле дублируется - на стороне сервера и на стороне клиента.

Быть кодером необязательно, чтобы понять, что делают эти отрывки кода, и понять, что они повторяют друг друга

// Код с клиента Minecraft
if (this.fallTime++ == 0) {
    BlockPos blockpos = new BlockPos(this);
    
    if (this.worldObj.getBlockState(blockpos).getBlock() == block) {
        this.worldObj.setBlockToAir(blockpos);
    } else if (!this.worldObj.isRemote) {
        this.setDead();
        return;
    }
}
// Код с сервера Spigot
BlockPosition blockposition;
if (this.ticksLived++ == 0) {
    blockposition = new BlockPosition(this);
    if (this.world.getType(blockposition).getBlock() == block && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition.getX(), blockposition.getY(), blockposition.getZ(), Blocks.AIR, 0).isCancelled()) {
        this.world.setAir(blockposition);
        this.world.spigotConfig.antiXrayInstance.updateNearbyBlocks(this.world, blockposition);
    } else if (!this.world.isClientSide) {
        this.die();
        return;
    }
}

Но одно отличие все же есть - второй код не будет вызван при замене блока на падающий. Да, во время выключенной физики выполняется только второй блок с условиями, где этот блок просто "умирает". В следующие моменты в любом случае падающий блок появится и удалит блок, на котором он был, соответственно клиенту необязательно сразу же удалять появившийся у него падающий блок (на самом деле там было еще много процессов, в том числе отправка пакета на создание такого блока), потому что еще не факт, что он действительно будет падать после отмены ивентов физики.

Делаем совсем немножечко изменений и получаем возможно не очень красивый результат, ведь все же на микромомент падающий блок успевает появиться на клиенте из-за получения пакета от сервера, но тут я бессилен, ядро редактировать у меня нет возможностей.

if (this.fallTime++ == 0) {
    // VimeWorld start
    // BlockPos blockpos = new BlockPos(this);
    // if (this.worldObj.getBlockState(blockpos).getBlock() == block) {
    //     this.worldObj.setBlockToAir(blockpos);
    // } else
    // VimeWorld end
    if (!this.worldObj.isRemote) {
        this.setDead();
        return;
    }
}

Забавный факт, что помимо исправления визуального бага с сыпучими блоками, исчезает и надоедливый баг, когда невозможно спамить такими блоками, например при строительстве на BuildBattle

  Показать содержимое

До: 

После:

 

 

Не верю, все что ты написал было енотакином сделано еще пол года назад!

Ссылка на комментарий
14 часов назад, iKpudka сказал:

UPD: решили все же чинить баг на самом серверном ядре, так как это априори правильнее, но можно почитать и мои танцы в клиенте

 

Краткий ввод, почему вообще происходит такой визуальный баг: когда сервер заменяет где-либо блок с одного типа на другой, он проверяет, нет ли у этого блока гравитации, и если есть, то начинает спавнить EntityFallingBlock, который мы знаем в простонародье как "падающий блок". Конечно, в Spigot есть возможность менять блоки без применения физики, оно и понятно, ведь на самом деле блок никуда не пропадает, а остается на своем месте, просто визуально для игрока он пропадает, и мы скоро узнаем почему

Я считаю, что фикс должен быть немного другим. Действительно сложно постоянно стрелять по бетону, чтобы он не падал. Поэтому я решил обратиться к коду клиента и сервера Minecraft. Буду честен, копался довольно продолжительное время, дебажил все процессы, которые происходят и не происходят.

И наконец - удалось найти косяк! Дело в том, что оригинальный код подразумевает удаление блока в том месте, где появляется сущность падающего блока. Другой вопрос, что такой код на самом деле дублируется - на стороне сервера и на стороне клиента.

Быть кодером необязательно, чтобы понять, что делают эти отрывки кода, и понять, что они повторяют друг друга

// Код с клиента Minecraft
if (this.fallTime++ == 0) {
    BlockPos blockpos = new BlockPos(this);
    
    if (this.worldObj.getBlockState(blockpos).getBlock() == block) {
        this.worldObj.setBlockToAir(blockpos);
    } else if (!this.worldObj.isRemote) {
        this.setDead();
        return;
    }
}
// Код с сервера Spigot
BlockPosition blockposition;
if (this.ticksLived++ == 0) {
    blockposition = new BlockPosition(this);
    if (this.world.getType(blockposition).getBlock() == block && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition.getX(), blockposition.getY(), blockposition.getZ(), Blocks.AIR, 0).isCancelled()) {
        this.world.setAir(blockposition);
        this.world.spigotConfig.antiXrayInstance.updateNearbyBlocks(this.world, blockposition);
    } else if (!this.world.isClientSide) {
        this.die();
        return;
    }
}

Но одно отличие все же есть - второй код не будет вызван при замене блока на падающий. Да, во время выключенной физики выполняется только второй блок с условиями, где этот блок просто "умирает". В следующие моменты в любом случае падающий блок появится и удалит блок, на котором он был, соответственно клиенту необязательно сразу же удалять появившийся у него падающий блок (на самом деле там было еще много процессов, в том числе отправка пакета на создание такого блока), потому что еще не факт, что он действительно будет падать после отмены ивентов физики.

Делаем совсем немножечко изменений и получаем возможно не очень красивый результат, ведь все же на микромомент падающий блок успевает появиться на клиенте из-за получения пакета от сервера, но тут я бессилен, ядро редактировать у меня нет возможностей.

if (this.fallTime++ == 0) {
    // VimeWorld start
    // BlockPos blockpos = new BlockPos(this);
    // if (this.worldObj.getBlockState(blockpos).getBlock() == block) {
    //     this.worldObj.setBlockToAir(blockpos);
    // } else
    // VimeWorld end
    if (!this.worldObj.isRemote) {
        this.setDead();
        return;
    }
}

Забавный факт, что помимо исправления визуального бага с сыпучими блоками, исчезает и надоедливый баг, когда невозможно спамить такими блоками, например при строительстве на BuildBattle

  Скрыть содержимое

До: 

После:

 

 

Круто, что об этом задумались, хоть и долго 

Ссылка на комментарий

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас
  • Сейчас на странице   0 пользователей

    • Нет пользователей, просматривающих эту страницу.
×
×
  • Создать...