Проверка целостности кровати на спавнпоинте (и не только)

Сообщения
71
Лучшие ответы
1
Реакции
11
Версия Minecraft
1.14.4
Всем привет. Цель предельно проста - сделать магическое зеркало из террарии в кубаче, однако и тут я столкнулся с двумя(или даже тремя) вопросами. Тему собирался писать неоднократно, но потом в голову приходило что-то вроде "А что, если..." и я уходил обратно пробовать. Сейчас, уже вдоволь напробовавшись, таки решил написать.


"Код":
Java:
    @Override
    public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
        ItemStack itemstack = playerIn.getHeldItem(handIn);
        BlockPos spawnPoint = playerIn.getBedLocation(playerIn.getSpawnDimension());
        if (!playerIn.abilities.isCreativeMode) {
            playerIn.getCooldownTracker().setCooldown(this, 100);
        }

        if (spawnPoint == null) {
            playerIn.sendMessage(new TranslationTextComponent("block.minecraft.bed.not_valid"));
            return new ActionResult<>(ActionResultType.FAIL, itemstack);
        } else {
            worldIn.playSound(playerIn, playerIn.posX, playerIn.posY, playerIn.posZ, ModSounds.TELEPORT, SoundCategory.PLAYERS, 1.0F, 1.0F);
            if (!worldIn.isRemote) {
                playerIn.setPositionAndUpdate(spawnPoint.getX(), spawnPoint.getY(), spawnPoint.getZ());
            }
            return new ActionResult<>(ActionResultType.SUCCESS, itemstack);
        }
    }
Что должен делать предмет: При клике ПКМ с небольшой задержкой телепортирует игрока к его кровати. если кровати нет - крякает об этом в чат.

Имеющиеся проблемы:
1. Если кровать еще ни разу не была установлена, игрока, как и должно быть, не телепортирует к точке спавна, однако звук телепортации всё равно воспроизводится, хотя не должен, поскольку телепортация не происходит.
2. После установки кровати всё работает подобно ожиданиям, однако при разрушении кровати игрока всё ещё телепортирует к предыдущему её местоположению. Нужно как-то при нажатии ПКМ обновлять её позицию.

Дополнительные задачи:
1. Необходимо реализовать задержку срабатывания зеркала. Т.е. нажал ПКМ, прошло пару секунд - игрока телепортировало. Я пока не искал как это реализовать,так как не решил предыдущие проблемы. Но если кто-то подскажет - буду благодарен.

P.S. - Как можно заметить по коду, я там уже столько всего наворотил в тщетных попытках решения имеющихся вопросов, что сам запутался.
 
Последнее редактирование:

tox1cozZ

aka Agravaine
Модератор
Сообщения
6,817
Лучшие ответы
412
Реакции
1,901
1. Весь метод оберни в !world.isRemote
2. В игроке, вроде, есть метод verifyBedLocation. Там проверяется что кровать рил стоит и не сломана.

1. Пишешь в нбт стака кулдаун, в апдейте считаешь время и тепаешь.
 
Сообщения
71
Лучшие ответы
1
Реакции
11
1. Весь метод оберни в !world.isRemote
Если я верно понял, так:

Java:
    @Override
    public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
        ItemStack itemstack = playerIn.getHeldItem(handIn);
        if (!worldIn.isRemote) {
            BlockPos spawnPoint = playerIn.getBedLocation(playerIn.getSpawnDimension());

            if (!playerIn.abilities.isCreativeMode) {
                playerIn.getCooldownTracker().setCooldown(this, 100);
            }

            if (spawnPoint == null) {
                playerIn.sendMessage(new TranslationTextComponent("block.minecraft.bed.not_valid"));
                return new ActionResult<>(ActionResultType.FAIL, itemstack);
            } else {
                worldIn.playSound(playerIn, playerIn.posX, playerIn.posY, playerIn.posZ, ModSounds.TELEPORT, SoundCategory.PLAYERS, 1.0F, 1.0F);
                playerIn.setPositionAndUpdate(spawnPoint.getX(), spawnPoint.getY(), spawnPoint.getZ());
            }
        }
        return new ActionResult<>(ActionResultType.SUCCESS, itemstack);
    }
Исходя из этого:
Звук на сервер воспроизводиться не должен, насколько мне известно, и с такой обёрткой оно звук вообще не воспроизводит.
Итемстак вынес за !isRemote чтоб нижний return возвращал результат действия нормально.

2. В игроке, вроде, есть метод verifyBedLocation. Там проверяется что кровать рил стоит и не сломана.
Возможно, я не там ищу, но найти не могу.


1. Пишешь в нбт стака кулдаун, в апдейте считаешь время и тепаешь.
Спасибо, буду пробовать.
 

tox1cozZ

aka Agravaine
Модератор
Сообщения
6,817
Лучшие ответы
412
Реакции
1,901
Звук на сервер воспроизводиться не должен, насколько мне известно, и с такой обёрткой оно звук вообще не воспроизводит.
Метод в мире кривой, он воспроизводит звук всем кроме текущего игрока. И там не воспроизведение на сервере, а отправка пакета всем рядом со звуком. Посмотри в снежке, например, как воспроизводится звук бросания.

Возможно, я не там ищу, но найти не могу.
В 1.12.2 так: EntityPlayer#getBedSpawnLocation. В 1.14 без понятия, ищи похожее...
 
Сообщения
71
Лучшие ответы
1
Реакции
11
Метод в мире кривой, он воспроизводит звук всем кроме текущего игрока. И там не воспроизведение на сервере, а отправка пакета всем рядом со звуком. Посмотри в снежке, например, как воспроизводится звук бросания.
Отлично, этот вопрос решен. Звук воспроизвожу следующим образом:
Java:
worldIn.playSound((PlayerEntity)null, playerIn.posX, playerIn.posY, playerIn.posZ, ModSounds.TELEPORT, SoundCategory.NEUTRAL, 1.0F, 1.0F);
Не совсем понимаю суть сего каста, ну да ладно. Вечером разберу. Сейчас буду пробовать решить второй вопрос.
 
Сообщения
71
Лучшие ответы
1
Реакции
11
В 1.12.2 так: EntityPlayer#getBedSpawnLocation. В 1.14 без понятия, ищи похожее...
Вот, что удалось найти:

IForgeBlockState#getBedSpawnPosition:
    /**
     * Returns the position that the sleeper is moved to upon
     * waking up, or respawning at the bed.
     *
     * @param world The current world
     * @param pos Block position in world
     * @param sleeper The sleeper or camera entity, null in some cases.
     * @return The spawn position
     */
    default Optional<Vec3d> getBedSpawnPosition(EntityType<?> type, IWorldReader world, BlockPos pos, @Nullable LivingEntity sleeper)
    {
        return getBlockState().getBlock().getBedSpawnPosition(type, getBlockState(), world, pos, sleeper);
    }

PlayerEntity#getBedLocation:
   @Deprecated //Forge: Use Dimension sensitive version
   public BlockPos getBedLocation() {
      return getBedLocation(this.dimension);
   }

   /**
    * A dimension aware version of getBedLocation.
    * @param dim The dimension to get the bed spawn for
    * @return The player specific spawn location for the dimension.  May be null.
    */
   public BlockPos getBedLocation(net.minecraft.world.dimension.DimensionType dim) {
      return dim == net.minecraft.world.dimension.DimensionType.OVERWORLD ? spawnPos : spawnPosMap.get(dim.getRegistryName());
   }
Первый вариант больше похож на правду, сейчас попробую заюзать, правда хз как :D
 
Сообщения
71
Лучшие ответы
1
Реакции
11
2. После установки кровати всё работает подобно ожиданиям, однако при разрушении кровати игрока всё ещё телепортирует к предыдущему её местоположению. Нужно как-то при нажатии ПКМ обновлять её позицию.
С этим пока грустно - всё ещё не получается.
Либо методы из предыдущего сообщения не подходят, либо я не догоняю.
 
Сообщения
5,131
Лучшие ответы
160
Реакции
877
У тебя в предмете запоминается спавн-поинт? Зачем? Просто каждый раз получай его из мира. Если кровать сломается, спавн-поинт сам сетнется на общий спавн
 

tox1cozZ

aka Agravaine
Модератор
Сообщения
6,817
Лучшие ответы
412
Реакции
1,901
Не сетнется он. При респавне проверяется целостность кровати каждый раз.

Тс, глянь в респавне игрока код
 
Сообщения
71
Лучшие ответы
1
Реакции
11
У тебя в предмете запоминается спавн-поинт?
Попробовал запоминать только после ручной проверки, не помогло.

Чтоб не создавать каждый раз новый BlockPos при получении кординат x,y и z во время вызова setPositionAndUpdate. По идее, оно при каждом ПКМ перезаписывает эту координату для дальнейшего использования.

Тс, глянь в респавне игрока код
Смотрю, еще раз смотрю, а потом еще раз - ничего полезного не вижу. Сейчас пытаюсь дебагом методом тыка найти нужный метод из класса PlayerEntity.
 
Сообщения
71
Лучшие ответы
1
Реакции
11
Решил, всем спасибо!

P.S. Смотреть в PlayerList#recreatePlayerEntity
 
Сообщения
5,131
Лучшие ответы
160
Реакции
877
Чтоб не создавать каждый раз новый BlockPos при получении кординат x,y и z во время вызова setPositionAndUpdate
Щас бы париться из-за единичных аллокаций в бакэнде :m_faceplam:
~~~
Ответ на реакцию "Чего?":
Того! Одна аллокация объекта, которая происходит один раз за телепорт картину не изменит. Минисруфт и без тебя насрет в кучу(в прямом смысле, куча - способ огранизации памяти в jvm).
Бояться аллокаций надо, если твой код выполняется много раз за маленький промежуток времени или если это код рендера(очистка кучи сборщиком мусора может вызывать фризы)
 
Последнее редактирование:
Сверху