Стреляет оно факелам, которые при попадании в блок "устанавливаются" на него. Здесь стоит отметить существенное отличие от стрел, которые просто в произвольном порядке втыкаются в объект.
Здесь речь пойдет именно об корректной установки факела на блок. То же самое что и рукой, но только на расстоянии выстрела.
Как оно принципиально устроено?
ItemTorchGun ( аналог лука) стреляет снарядами EntityFlyTorch (аналог EntityArrow)
Но в отличие от обычной стрелы , у EntityFlyTorch в методе onUpdate
в окрестности этого куска кода:
xTile = movingobjectposition[paste][/paste]blockX; yTile = movingobjectposition[paste][/paste]blockY; zTile = movingobjectposition[paste][/paste]blockZ; inTile = worldObj[paste][/paste]getBlockId(xTile, yTile, zTile); motionX = (float)(movingobjectposition[paste][/paste]hitVec[paste][/paste]xCoord - posX); motionY = (float)(movingobjectposition[paste][/paste]hitVec[paste][/paste]yCoord - posY); motionZ = (float)(movingobjectposition[paste][/paste]hitVec[paste][/paste]zCoord - posZ); float f1 = MathHelper[paste][/paste]sqrt_double(motionX * motionX + motionY * motionY + motionZ * motionZ); posX -= (motionX / (double)f1) * 0[paste][/paste]05000000074505806D; posY -= (motionY / (double)f1) * 0[paste][/paste]05000000074505806D; posZ -= (motionZ / (double)f1) * 0[paste][/paste]05000000074505806D; worldObj[paste][/paste]playSoundAtEntity(this, "random[paste][/paste]drr", 1[paste][/paste]0F, 1[paste][/paste]2F / (rand[paste][/paste]nextFloat() * 0[paste][/paste]2F + 0[paste][/paste]9F)); inGround = true; arrowShake = 7;произведено существенное изменение - а именно :
1. inTile = worldObj.getBlockId(xTile, yTile, zTile); - эта строчка говорит о том, что мы с легкостью можем получить ID блока на который нам надо установить факел.
Следовательно, прямо в этот блок мы можем дописать команду которая создает блок BlockTorch и ставит его на указанный ID блока в которого воткнулся наш EntityFlyTorch
2. В конце этого куска нам необходимо дописать setEntityDead();, чтобы наш факел исчез как снаряд, и остался только блок BlockTorch (установленный факел на стене)
В принципе всё просто и легко, НО сложности возникают с первым пунктом - какими командами установить блок ?
Давайте обратимся классу ItemBolck. там есть такая функция :
public boolean onItemUse(ItemStack itemstack, EntityPlayer entityplayer, World world, int i, int j, int k, int l) { if(world[paste][/paste]getBlockId(i, j, k) == Block[paste][/paste]snow[paste][/paste]blockID) { l = 0; } else { if(l == 0) { j--; } if(l == 1) { j++; } if(l == 2) { k--; } if(l == 3) { k++; } if(l == 4) { i--; } if(l == 5) { i++; } } if(itemstack[paste][/paste]stackSize == 0) { return false; } if(world[paste][/paste]canBlockBePlacedAt(blockID, i, j, k, false)) { Block block = Block[paste][/paste]blocksList[blockID]; if(world[paste][/paste]setBlockAndMetadataWithNotify(i, j, k, blockID, func_21012_a(itemstack[paste][/paste]getItemDamage()))) { Block[paste][/paste]blocksList[blockID][paste][/paste]onBlockPlaced(world, i, j, k, l); Block[paste][/paste]blocksList[blockID][paste][/paste]onBlockPlacedBy(world, i, j, k, entityplayer); world[paste][/paste]playSoundEffect((float)i + 0[paste][/paste]5F, (float)j + 0[paste][/paste]5F, (float)k + 0[paste][/paste]5F, block[paste][/paste]stepSound[paste][/paste]func_1145_d(), (block[paste][/paste]stepSound[paste][/paste]func_1147_b() + 1[paste][/paste]0F) / 2[paste][/paste]0F, block[paste][/paste]stepSound[paste][/paste]func_1144_c() * 0[paste][/paste]8F); itemstack[paste][/paste]stackSize--; } return true; } else { return false; } }
первая часть кода мне не известна, а вот во второй - происходит проверка можно ли в заданных координатах поставить блок, затем блок ставится и проигрывается звук установки блока.
Следовательно наш EntityFlyTorch должен проверить if(world.canBlockBePlacedAt(blockID, i, j, k, false)) можно ли там поставить BlockTorch , где i,j,k соответственно равны xTile, yTile, zTile, мне очень хочется надеяться что это именно те координаты которые нужны.
Для того чтобы поставить BlockTorch мы воспользуемся его методом
public void onBlockPlaced(World world, int i, int j, int k, int l)
int i, int j, int k эти параметры мы знаем, а вот откуда взять int l я честно не знаю... эта переменная сильно напоминает на сторону блока,
я пытался лазить по всем java файлам МК, пытаясь найти кто-же передает эти четыре переменные -
самый крайний метод, который я нашел это
public boolean sendPlaceBlock(EntityPlayer entityplayer, World world, ItemStack itemstack, int i, int j, int k, int l)
в классе playerController , мне так и не известно откуда он получает эти int i, int j, int k, int - если кто-нить найдет способ обойтись без них, то плиз отпишитесь в тему.