Дроп в AABB блока и результат.

Доброго времени суток. Возник вопрос, как сделать так, что бы если игрок в AABB блока кидал некоторые предметы и в следствии они пропадали, давая другой предмет? Допустим: закидываем три алмаза в AABB блока и получаем одно золотое яблоко. Какой и куда написать код вообще не могу приложить ума. Подскажите пожалуйста.
 

timaxa007

Модератор
5,831
409
672
Можно писать в любой апдейт (апдейт блока, апдейт TileEntity), но главное правильно написать код.
Пример с TileEntity можно взять с воронки.
С помощью AxisAlignedBB, проверять на EntityItem в его области.
Узнать что за ItemStack в EntityItem.
Код:
ItemStack is_entity = entity_item.getEntityItem();
Дальше нужно создавать проверку, находиться-ли нужное количество алмазов. Если хватает, то нужное количество отнимается (если равно трём, то "entity_item.setDead();"). И спавниться новый EntityItem с ItemStack c предметом золотое яблоко (и возможно с нужной метадатой).
 

timaxa007

Модератор
5,831
409
672
Пример для TileEntity:
[youtube]qm8oPUIkBMs[/youtube]
Код:
public void updateEntity() {

if (!this.worldObj.isRemote) {

double d0 = 0.0625D;

AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(
(double)this.xCoord, (double)this.yCoord, (double)this.zCoord, 
(double)this.xCoord + 1.0D, (double)this.yCoord + 1.0D, (double)this.zCoord + 1.0D).expand(d0, d0, d0);
List list = this.worldObj.getEntitiesWithinAABB(Entity.class, axisalignedbb);
Iterator iterator = list.iterator();
Entity entity = null;

while(iterator.hasNext()) {
entity = (Entity)iterator.next();

if (entity instanceof EntityItem) {
EntityItem entity_item = (EntityItem)entity;
ItemStack is_entity = entity_item.getEntityItem();

if (is_entity.getItem() == Items.diamond) {
if (is_entity.stackSize >= 3) {

EntityItem entityitem = new EntityItem(this.worldObj, (double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D, new ItemStack(Items.golden_apple));
entityitem.delayBeforeCanPickup = 10;
world.spawnEntityInWorld(entityitem);
                
if (is_entity.stackSize == 3) entity_item.setDead(); else is_entity.stackSize -= 3;

break;
}

}

}

}

}

}
 

timaxa007

Модератор
5,831
409
672
Обновил код: добавил "break;" и переставил условия "if (!this.worldObj.isRemote)" (удалялось больше, чем надо, по этому была недосдача золотых яблок).
 
4,045
63
645
Тимаха!
Только начал осваивать тайл, решил для затравки попробовать твой пример.
Тупо скопировал и вставил в тайл:
Код:
package ru.liahim.Testmod.tileentity;

import java.util.Iterator;
import java.util.List;

import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;


public class TestTileEntity extends TileEntity {
    
    public void updateEntity() {

        if (!this.worldObj.isRemote) {

        double d0 = 0.0625D;

        AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(
        (double)this.xCoord, (double)this.yCoord, (double)this.zCoord, 
        (double)this.xCoord + 1.0D, (double)this.yCoord + 1.0D, (double)this.zCoord + 1.0D).expand(d0, d0, d0);
        List list = this.worldObj.getEntitiesWithinAABB(Entity.class, axisalignedbb);
        Iterator iterator = list.iterator();
        Entity entity = null;

        while(iterator.hasNext()) {
        entity = (Entity)iterator.next();

        if (entity instanceof EntityItem) {
        EntityItem entity_item = (EntityItem)entity;
        ItemStack is_entity = entity_item.getEntityItem();

        if (is_entity.getItem() == Items.diamond) {
        if (is_entity.stackSize >= 3) {

        EntityItem entityitem = new EntityItem(this.worldObj, (double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D, new ItemStack(Items.golden_apple));
        entityitem.delayBeforeCanPickup = 10;
        worldObj.spawnEntityInWorld(entityitem);
                        
        if (is_entity.stackSize == 3) entity_item.setDead(); else is_entity.stackSize -= 3;

        break;
        }

        }

        }

        }

        }

        }
    
       @Override
       public void writeToNBT(NBTTagCompound par1)
       {
          super.writeToNBT(par1);
       }

       @Override
       public void readFromNBT(NBTTagCompound par1)
       {
          super.readFromNBT(par1);
       }
    }

Тайл зарегистрировал в init:
Код:
GameRegistry.registerTileEntity(TestTileEntity.class, "testTileEntity");

Ну, и в блок пихнул:
Код:
public TileEntity createTileEntity(World world, int metadata)
    {
       return new TestTileEntity();
    }

Однако, ничего не фурычит.
Что я делаю не так? Наставь на путь истинный )))

Спасибо )
 

timaxa007

Модератор
5,831
409
672
А в блок ты вставил "implements ITileEntityProvider"? И надо "createNewTileEntity", а не "createTileEntity":
Код:
@Override
public TileEntity createNewTileEntity(World world, int meta) {
return new TestTileEntity();
}
[merge_posts_bbcode]Добавлено: 04.09.2015 23:01:03[/merge_posts_bbcode]

На 1.7.х желательно TileEntity зарегистрировать в preInit. Я не знаю какой эффект будет если его регистрировать в Init'е. На 1.6.х в Init, нормально.
 
4,045
63
645
Так... Вот сейчас добавил, проверил... Неа. Не фурычит (
Он ещё ругался на world.spawnEntityInWorld(entityitem);
[merge_posts_bbcode]Добавлено: 05.09.2015 00:02:35[/merge_posts_bbcode]

О! Про преинит ща попробую.

[merge_posts_bbcode]Добавлено: 05.09.2015 00:04:11[/merge_posts_bbcode]

Не... чё-т нифига (
 

timaxa007

Модератор
5,831
409
672
Может, что-то не то импортировал?
Код:
import java.util.Iterator;
import java.util.List;
import net.minecraft.entity.Entity;
У меня не подчёркивает.
 

timaxa007

Модератор
5,831
409
672
Liahim написал(а):
Он ещё ругался на world.spawnEntityInWorld(entityitem);
На "world" или "worldObj" ругаеться? Потомучто у тебя в коде "worldObj" написан.
 
4,045
63
645
Ругался на world, поэтому я заменил на worldObj.


При этом я сейчас попробовал твой же приём из этого вопроса: http://forum.mcmodding.ru/viewtopic.php?id=2216

Всё работает отлично. А вот с яблоками нет.
[merge_posts_bbcode]Добавлено: 05.09.2015 00:25:34[/merge_posts_bbcode]

Ну, на самом деле, основная цель была именно решить вопрос про моба ))) И она решилась.
Так что спасибо )
Только вот ещё вопрос возник: можно ли таким же образом организовать таяние снега вокруг блока? Или это решается проще?

Я так до конца и не понял, как это решено в тех же факелах, например.
 

timaxa007

Модератор
5,831
409
672
Проще, и это делается не с помощью факела, а из-за источника света. И можно и без "AxisAlignedBB". Просто в апдейте проверяешь местность и с подходящими блоками, будет выполняться то или иное действие.
 
4,045
63
645
В апдейте самого блока?
Ну, это у меня сделано... только слишком всё громоздко выглядит, да и тик апдейт не быстрый.

Просто я заметил, что от факела снег тает как бы по радиусу. Подумал, не иначе от расстояние от блока измеряет, а это уже AxisAlignedBB.
 
1,239
2
24
Не будет пахать по плюсовым координатам.Т.е. если колизия по x+ или y+ или z+ а координаты предмета например 95.8, то он столкнулся с блоком на координате 96:
Код:
floor(95.8) = 95
на позиции 95 нет твоего блока :/
Из сорцов майна

Код:
this.isCollidedHorizontally = d6 != p_70091_1_ || d8 != p_70091_5_;
this.isCollidedVertically = d7 != p_70091_3_;
А вот так проверяет , он ходит и ищет колизию по этим бб
Код:
list = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.addCoord(d6, p_70091_3_, d8));
 
4,045
63
645
А может надо делать так? :D
Код:
AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(
        (double)this.xCoord - 0.5D, (double)this.yCoord - 0.5D, (double)this.zCoord - 0.5D, 
        (double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D).expand(d0, d0, d0);


Вот координаты блока в обычном world находятся в наименьшей его точке, а про worldObj не знаю ))) Может они посередине вставлены.

Но это я так... несу бред.
 

timaxa007

Модератор
5,831
409
672
Liahim, на практике, координаты (хоть в int значени, хоть в double значении) блока не являются серединой блока, они являются углом у блока.
Так кажется было легче сделать, в положительную по 1,0 стороны рендерить блок, чем в положительную и отрицательную по 0,5 в каждую сторону.
 
4,045
63
645
Тимаха, а ты говорил, что этот метод можно не только в тайл кидать, но и в любой апдейт.
Видимо, для моих нужд будет лучше обойтись всё-таки без тайла.

Закинул его с тикАпдейт блока (работает, но медленно).

Но что-то никак не получается увеличить скорость тиканья.
Код:
public int tickRate(World p_149738_1_)
    {
        return 10;
    }
 
Что опять не так?
 

timaxa007

Модератор
5,831
409
672
Liahim, как ни странно но у меня тоже самое.
У меня почти у всех блоков метод updateTick, странно себя ведёт. То рандомно, то во-обще не работает, то очень не часто происходит update - и из-за этого я часто пользовался TileEntity. Сейчас я создаю подобия TileEntity. И скорее всего создам два этого подобия:
- Один для создания контейнеров, чтобы можно было делать типа нычек. Спрятанные вещи в дупле дерева, закопанные вещи и т.п..
- Второй для рендера моделей.
И т.п.
 
Сверху