Stránka 1 z 1

Programování

Napsal: 10 úno 2016, 21:02
od WorkiS
Zdravím,

chtěl bych se zeptat, potřebuji udělat to, že po zadání příkazu /firehorse se spawne Kůň a po celé délce jeho života kolem něho bude Particly ohně.
Vše mám kromě toho, že nevím jak napsat to, aby kolem něho byly ty particle. Tedy respektive nevím co dát do for.

Aktuální kód:

Kód: Vybrat vše

package me.domino.horsefire;

import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Horse.Variant;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

public class Main extends JavaPlugin {
   
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
        Player player = (Player) sender;
        if(cmd.getName().equalsIgnoreCase("firehorse")){
            Horse horse = (Horse) player.getWorld().spawnEntity(player.getLocation(), EntityType.HORSE);
            horse.setBreed(true);
            horse.setAdult();
            horse.setVariant(Variant.SKELETON_HORSE);
            horse.setCustomName("Kůň hráče " + player.getDisplayName());
        }
        return false;
    }   

}


Díky moc

Re: Programování

Napsal: 10 úno 2016, 21:56
od Hanakocz
Pozor, následující kód je dekompilovaný pro Forge a budeš si muset najít sám classy a funkce pro Bukkit, ale mohlo by ti to ukázat, jak na to. Základ (kód MC ) je stejný, takže se to zas až tak lišit nebude...Víceméně budeš používat komplet vanilla funkce.

Taková existující entita, která spawnuje particly, tak je Wolf, když se oklepává. Takže si z ní můžeš jistě něco půjčit (a dokonce jak wolf, tak horse extendujou stejné parent classy, takže o to líp)
Tu je celá class (vanilla MC dekompilované pro Forge) :
[code=java file=EntityWolf.class]package net.minecraft.entity.passive;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.BlockColored;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackOnCollide;
import net.minecraft.entity.ai.EntityAIBeg;
import net.minecraft.entity.ai.EntityAIFollowOwner;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILeapAtTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMate;
import net.minecraft.entity.ai.EntityAIOwnerHurtByTarget;
import net.minecraft.entity.ai.EntityAIOwnerHurtTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAITargetNonTamed;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.monster.EntityGhast;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.pathfinding.PathEntity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;

public class EntityWolf extends EntityTameable
{
private float field_70926_e;
private float field_70924_f;
/** true is the wolf is wet else false */
private boolean isShaking;
private boolean field_70928_h;
/** This time increases while wolf is shaking and emitting water particles. */
private float timeWolfIsShaking;
private float prevTimeWolfIsShaking;
private static final String __OBFID = "CL_00001654";

public EntityWolf(World p_i1696_1_)
{
super(p_i1696_1_);
this.setSize(0.6F, 0.8F);
this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(2, this.aiSit);
this.tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F));
this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 1.0D, true));
this.tasks.addTask(5, new EntityAIFollowOwner(this, 1.0D, 10.0F, 2.0F));
this.tasks.addTask(6, new EntityAIMate(this, 1.0D));
this.tasks.addTask(7, new EntityAIWander(this, 1.0D));
this.tasks.addTask(8, new EntityAIBeg(this, 8.0F));
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(9, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIOwnerHurtByTarget(this));
this.targetTasks.addTask(2, new EntityAIOwnerHurtTarget(this));
this.targetTasks.addTask(3, new EntityAIHurtByTarget(this, true));
this.targetTasks.addTask(4, new EntityAITargetNonTamed(this, EntitySheep.class, 200, false));
this.setTamed(false);
}

protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.30000001192092896D);

if (this.isTamed())
{
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(20.0D);
}
else
{
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(8.0D);
}
}

/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}

/**
* Sets the active target the Task system uses for tracking
*/
public void setAttackTarget(EntityLivingBase p_70624_1_)
{
super.setAttackTarget(p_70624_1_);

if (p_70624_1_ == null)
{
this.setAngry(false);
}
else if (!this.isTamed())
{
this.setAngry(true);
}
}

/**
* main AI tick function, replaces updateEntityActionState
*/
protected void updateAITick()
{
this.dataWatcher.updateObject(18, Float.valueOf(this.getHealth()));
}

protected void entityInit()
{
super.entityInit();
this.dataWatcher.addObject(18, new Float(this.getHealth()));
this.dataWatcher.addObject(19, new Byte((byte)0));
this.dataWatcher.addObject(20, new Byte((byte)BlockColored.func_150032_b(1)));
}

protected void func_145780_a(int p_145780_1_, int p_145780_2_, int p_145780_3_, Block p_145780_4_)
{
this.playSound("mob.wolf.step", 0.15F, 1.0F);
}

/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound p_70014_1_)
{
super.writeEntityToNBT(p_70014_1_);
p_70014_1_.setBoolean("Angry", this.isAngry());
p_70014_1_.setByte("CollarColor", (byte)this.getCollarColor());
}

/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound p_70037_1_)
{
super.readEntityFromNBT(p_70037_1_);
this.setAngry(p_70037_1_.getBoolean("Angry"));

if (p_70037_1_.hasKey("CollarColor", 99))
{
this.setCollarColor(p_70037_1_.getByte("CollarColor"));
}
}

/**
* Returns the sound this mob makes while it's alive.
*/
protected String getLivingSound()
{
return this.isAngry() ? "mob.wolf.growl" : (this.rand.nextInt(3) == 0 ? (this.isTamed() && this.dataWatcher.getWatchableObjectFloat(18) < 10.0F ? "mob.wolf.whine" : "mob.wolf.panting") : "mob.wolf.bark");
}

/**
* Returns the sound this mob makes when it is hurt.
*/
protected String getHurtSound()
{
return "mob.wolf.hurt";
}

/**
* Returns the sound this mob makes on death.
*/
protected String getDeathSound()
{
return "mob.wolf.death";
}

/**
* Returns the volume for the sounds this mob makes.
*/
protected float getSoundVolume()
{
return 0.4F;
}

protected Item getDropItem()
{
return Item.getItemById(-1);
}

/**
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
* use this to react to sunlight and start to burn.
*/
public void onLivingUpdate()
{
super.onLivingUpdate();

if (!this.worldObj.isRemote && this.isShaking && !this.field_70928_h && !this.hasPath() && this.onGround)
{
this.field_70928_h = true;
this.timeWolfIsShaking = 0.0F;
this.prevTimeWolfIsShaking = 0.0F;
this.worldObj.setEntityState(this, (byte)8);
}
}

/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
this.field_70924_f = this.field_70926_e;

if (this.func_70922_bv())
{
this.field_70926_e += (1.0F - this.field_70926_e) * 0.4F;
}
else
{
this.field_70926_e += (0.0F - this.field_70926_e) * 0.4F;
}

if (this.func_70922_bv())
{
this.numTicksToChaseTarget = 10;
}

if (this.isWet())
{
this.isShaking = true;
this.field_70928_h = false;
this.timeWolfIsShaking = 0.0F;
this.prevTimeWolfIsShaking = 0.0F;
}
else if ((this.isShaking || this.field_70928_h) && this.field_70928_h)
{
if (this.timeWolfIsShaking == 0.0F)
{
this.playSound("mob.wolf.shake", this.getSoundVolume(), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
}

this.prevTimeWolfIsShaking = this.timeWolfIsShaking;
this.timeWolfIsShaking += 0.05F;

if (this.prevTimeWolfIsShaking >= 2.0F)
{
this.isShaking = false;
this.field_70928_h = false;
this.prevTimeWolfIsShaking = 0.0F;
this.timeWolfIsShaking = 0.0F;
}

if (this.timeWolfIsShaking > 0.4F)
{
float f = (float)this.boundingBox.minY;
int i = (int)(MathHelper.sin((this.timeWolfIsShaking - 0.4F) * (float)Math.PI) * 7.0F);

for (int j = 0; j < i; ++j)
{
float f1 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F;
float f2 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F;
this.worldObj.spawnParticle("splash", this.posX + (double)f1, (double)(f + 0.8F), this.posZ + (double)f2, this.motionX, this.motionY, this.motionZ);
}
}
}
}

@SideOnly(Side.CLIENT)
public boolean getWolfShaking()
{
return this.isShaking;
}

/**
* Used when calculating the amount of shading to apply while the wolf is shaking.
*/
@SideOnly(Side.CLIENT)
public float getShadingWhileShaking(float p_70915_1_)
{
return 0.75F + (this.prevTimeWolfIsShaking + (this.timeWolfIsShaking - this.prevTimeWolfIsShaking) * p_70915_1_) / 2.0F * 0.25F;
}

@SideOnly(Side.CLIENT)
public float getShakeAngle(float p_70923_1_, float p_70923_2_)
{
float f2 = (this.prevTimeWolfIsShaking + (this.timeWolfIsShaking - this.prevTimeWolfIsShaking) * p_70923_1_ + p_70923_2_) / 1.8F;

if (f2 < 0.0F)
{
f2 = 0.0F;
}
else if (f2 > 1.0F)
{
f2 = 1.0F;
}

return MathHelper.sin(f2 * (float)Math.PI) * MathHelper.sin(f2 * (float)Math.PI * 11.0F) * 0.15F * (float)Math.PI;
}

public float getEyeHeight()
{
return this.height * 0.8F;
}

@SideOnly(Side.CLIENT)
public float getInterestedAngle(float p_70917_1_)
{
return (this.field_70924_f + (this.field_70926_e - this.field_70924_f) * p_70917_1_) * 0.15F * (float)Math.PI;
}

/**
* The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
* use in wolves.
*/
public int getVerticalFaceSpeed()
{
return this.isSitting() ? 20 : super.getVerticalFaceSpeed();
}

/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource p_70097_1_, float p_70097_2_)
{
if (this.isEntityInvulnerable())
{
return false;
}
else
{
Entity entity = p_70097_1_.getEntity();
this.aiSit.setSitting(false);

if (entity != null && !(entity instanceof EntityPlayer) && !(entity instanceof EntityArrow))
{
p_70097_2_ = (p_70097_2_ + 1.0F) / 2.0F;
}

return super.attackEntityFrom(p_70097_1_, p_70097_2_);
}
}

public boolean attackEntityAsMob(Entity p_70652_1_)
{
int i = this.isTamed() ? 4 : 2;
return p_70652_1_.attackEntityFrom(DamageSource.causeMobDamage(this), (float)i);
}

public void setTamed(boolean p_70903_1_)
{
super.setTamed(p_70903_1_);

if (p_70903_1_)
{
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(20.0D);
}
else
{
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(8.0D);
}
}

/**
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
*/
public boolean interact(EntityPlayer p_70085_1_)
{
ItemStack itemstack = p_70085_1_.inventory.getCurrentItem();

if (this.isTamed())
{
if (itemstack != null)
{
if (itemstack.getItem() instanceof ItemFood)
{
ItemFood itemfood = (ItemFood)itemstack.getItem();

if (itemfood.isWolfsFavoriteMeat() && this.dataWatcher.getWatchableObjectFloat(18) < 20.0F)
{
if (!p_70085_1_.capabilities.isCreativeMode)
{
--itemstack.stackSize;
}

this.heal((float)itemfood.func_150905_g(itemstack));

if (itemstack.stackSize <= 0)
{
p_70085_1_.inventory.setInventorySlotContents(p_70085_1_.inventory.currentItem, (ItemStack)null);
}

return true;
}
}
else if (itemstack.getItem() == Items.dye)
{
int i = BlockColored.func_150032_b(itemstack.getItemDamage());

if (i != this.getCollarColor())
{
this.setCollarColor(i);

if (!p_70085_1_.capabilities.isCreativeMode && --itemstack.stackSize <= 0)
{
p_70085_1_.inventory.setInventorySlotContents(p_70085_1_.inventory.currentItem, (ItemStack)null);
}

return true;
}
}
}

if (this.func_152114_e(p_70085_1_) && !this.worldObj.isRemote && !this.isBreedingItem(itemstack))
{
this.aiSit.setSitting(!this.isSitting());
this.isJumping = false;
this.setPathToEntity((PathEntity)null);
this.setTarget((Entity)null);
this.setAttackTarget((EntityLivingBase)null);
}
}
else if (itemstack != null && itemstack.getItem() == Items.bone && !this.isAngry())
{
if (!p_70085_1_.capabilities.isCreativeMode)
{
--itemstack.stackSize;
}

if (itemstack.stackSize <= 0)
{
p_70085_1_.inventory.setInventorySlotContents(p_70085_1_.inventory.currentItem, (ItemStack)null);
}

if (!this.worldObj.isRemote)
{
if (this.rand.nextInt(3) == 0)
{
this.setTamed(true);
this.setPathToEntity((PathEntity)null);
this.setAttackTarget((EntityLivingBase)null);
this.aiSit.setSitting(true);
this.setHealth(20.0F);
this.func_152115_b(p_70085_1_.getUniqueID().toString());
this.playTameEffect(true);
this.worldObj.setEntityState(this, (byte)7);
}
else
{
this.playTameEffect(false);
this.worldObj.setEntityState(this, (byte)6);
}
}

return true;
}

return super.interact(p_70085_1_);
}

@SideOnly(Side.CLIENT)
public void handleHealthUpdate(byte p_70103_1_)
{
if (p_70103_1_ == 8)
{
this.field_70928_h = true;
this.timeWolfIsShaking = 0.0F;
this.prevTimeWolfIsShaking = 0.0F;
}
else
{
super.handleHealthUpdate(p_70103_1_);
}
}

@SideOnly(Side.CLIENT)
public float getTailRotation()
{
return this.isAngry() ? 1.5393804F : (this.isTamed() ? (0.55F - (20.0F - this.dataWatcher.getWatchableObjectFloat(18)) * 0.02F) * (float)Math.PI : ((float)Math.PI / 5F));
}

/**
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
* the animal type)
*/
public boolean isBreedingItem(ItemStack p_70877_1_)
{
return p_70877_1_ == null ? false : (!(p_70877_1_.getItem() instanceof ItemFood) ? false : ((ItemFood)p_70877_1_.getItem()).isWolfsFavoriteMeat());
}

/**
* Will return how many at most can spawn in a chunk at once.
*/
public int getMaxSpawnedInChunk()
{
return 8;
}

/**
* Determines whether this wolf is angry or not.
*/
public boolean isAngry()
{
return (this.dataWatcher.getWatchableObjectByte(16) & 2) != 0;
}

/**
* Sets whether this wolf is angry or not.
*/
public void setAngry(boolean p_70916_1_)
{
byte b0 = this.dataWatcher.getWatchableObjectByte(16);

if (p_70916_1_)
{
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 | 2)));
}
else
{
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & -3)));
}
}

/**
* Return this wolf's collar color.
*/
public int getCollarColor()
{
return this.dataWatcher.getWatchableObjectByte(20) & 15;
}

/**
* Set this wolf's collar color.
*/
public void setCollarColor(int p_82185_1_)
{
this.dataWatcher.updateObject(20, Byte.valueOf((byte)(p_82185_1_ & 15)));
}

public EntityWolf createChild(EntityAgeable p_90011_1_)
{
EntityWolf entitywolf = new EntityWolf(this.worldObj);
String s = this.func_152113_b();

if (s != null && s.trim().length() > 0)
{
entitywolf.func_152115_b(s);
entitywolf.setTamed(true);
}

return entitywolf;
}

public void func_70918_i(boolean p_70918_1_)
{
if (p_70918_1_)
{
this.dataWatcher.updateObject(19, Byte.valueOf((byte)1));
}
else
{
this.dataWatcher.updateObject(19, Byte.valueOf((byte)0));
}
}

/**
* Returns true if the mob is currently able to mate with the specified mob.
*/
public boolean canMateWith(EntityAnimal p_70878_1_)
{
if (p_70878_1_ == this)
{
return false;
}
else if (!this.isTamed())
{
return false;
}
else if (!(p_70878_1_ instanceof EntityWolf))
{
return false;
}
else
{
EntityWolf entitywolf = (EntityWolf)p_70878_1_;
return !entitywolf.isTamed() ? false : (entitywolf.isSitting() ? false : this.isInLove() && entitywolf.isInLove());
}
}

public boolean func_70922_bv()
{
return this.dataWatcher.getWatchableObjectByte(19) == 1;
}

/**
* Determines if an entity can be despawned, used on idle far away entities
*/
protected boolean canDespawn()
{
return !this.isTamed() && this.ticksExisted > 2400;
}

public boolean func_142018_a(EntityLivingBase p_142018_1_, EntityLivingBase p_142018_2_)
{
if (!(p_142018_1_ instanceof EntityCreeper) && !(p_142018_1_ instanceof EntityGhast))
{
if (p_142018_1_ instanceof EntityWolf)
{
EntityWolf entitywolf = (EntityWolf)p_142018_1_;

if (entitywolf.isTamed() && entitywolf.getOwner() == p_142018_2_)
{
return false;
}
}

return p_142018_1_ instanceof EntityPlayer && p_142018_2_ instanceof EntityPlayer && !((EntityPlayer)p_142018_2_).canAttackPlayer((EntityPlayer)p_142018_1_) ? false : !(p_142018_1_ instanceof EntityHorse) || !((EntityHorse)p_142018_1_).isTame();
}
else
{
return false;
}
}
}[/code]

Nás z toho zajímá hlavně tadle část:

[code=java file=Untitled.java]if (this.timeWolfIsShaking > 0.4F)
{
float f = (float)this.boundingBox.minY;
int i = (int)(MathHelper.sin((this.timeWolfIsShaking - 0.4F) * (float)Math.PI) * 7.0F);

for (int j = 0; j < i; ++j)
{
float f1 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F;
float f2 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width * 0.5F;
this.worldObj.spawnParticle("splash", this.posX + (double)f1, (double)(f + 0.8F), this.posZ + (double)f2, this.motionX, this.motionY, this.motionZ);
}
}[/code]

Co z toho použít a jak: Pracuje to s časem, jak dlouho se klepe (aby nelítaly furt jedním směrem, ale různě do stran) , ten ale měřit nebudeš, když to bude furt. Takže this.timeWolfIsShaking budeš muset nahradit nějakou jinou funkcí, která se bude periodicky v čase měnit...
Taky musíš this.width a bounding boxy nafitovat ke koňovi, aby se nespawnovaly partikly jen z třeba hlavy, ale z celýho těla....
A hlavně nepotřebuješ žádný IF , takže to z něj vyškub :P (teoreticky, pokud třeba nechceš zkoumat, zda je entita ve vodě, kde by to bylo vypnuté)

A kam s tím?
->
public void onLivingUpdate() se volá každý tick, takže stačí udělat, že se každý tick bude spawnovat particle. Pak jen musíš zajistit správný typ particlu a případně barvu, ale pokud ti bude fungovat tento zkopírovaný, pak ta další část bude hračka.

Zkusil jsem ještě najít, jaký typy particlů jsou, ale tam jsem toho moc nenašel, max prozkoumej net.minecraft.client.particle , ale jednoznačně jsem to nenašel. Ale můžeš zkusit "flame", "smoke" nebo tak.


PS: Alternativní (a možná jednodušší postup) by byl dát koňovi imunitu na oheň a dát mu do onLivingUpdate(), že hoří... :) Ale to by byl jen v ohni a nebyly by tam partikly. A čistě teoreticky to můžeš zkombinovat.

Re: Programování

Napsal: 10 úno 2016, 22:30
od WorkiS
Hele děkuji Ti moc, ale myslel jsem particle ohně. Myslím tím jako, že bude kolem něho oheň, ne že bude přímo hořet. Toto je snad, že bude "hořet".

Takže nějaký jiný způsob?

K+ jinak.

Re: Programování

Napsal: 10 úno 2016, 23:16
od Hanakocz
Však jsem ho popsal. Oheň jsem zmínil okrajově, že se dá taky použít.
Ve hře si spawni vlka, namoč ho a pak ho nech vylézt z vody a sleduj, jak se oklepe. Budou od něj lítat modrý kapky. Tobě stačí modrý a kapky nahradit červenými a plamínky. Ale funkce na to bude stejná. Chápeme se?

Teoreticky ještě můžeš kouknout na blaze, ale ten kolem sebe spawnuje "smoke" a ne flame...

Re: Programování

Napsal: 10 úno 2016, 23:25
od WorkiS
Ok díky.