So I’m trying to check if there’s a specific block in front of a mob that’s trying to get to a player…however I don’t know how to grab a live instance of the Mobs or what would be pushing them to chase a player…any help please?
Get the mob, and get the player. Then use a BlockRay
from the mob’s position to the player’s position, and check if there are any ‘hits’ along the way.
Please stand by Pie_flavor the great! I’m going to have tons of questions regarding this. as I’m Now making Mob Mechanics, and building from there. Of course I’ll have tons of questions but I’ll try not to take too much of your time
. K So first, do you mean get an instance of the mob and then use the TargetedEntity? For the first part? then use the BlockRay to see if there are any blocks along the way?
Right. Any mob’s getTarget()
returns who they’re trying to kill. So if you have a mob m
and player p = m.getTarget().get()
(assuming there is a target), then the code BlockRay.from(m.getLocation()).to(p.getLocation().getPosition()).build().hasNext()
should return a boolean whether there’s a block between them. You also may want to do another BlockRay
starting and ending one block more in the Y direction, because the first one would only check if there’s a block between their feet.
Edit: You probably don’t want stuff like grass, flowers, or torches to get in the way. So before build()
you’d add .skipFilter(h -> h.getLocation().getBlockType().getProperty(PassableProperty.class).map(Property::getValue).orElse(false))
Ok, now say I wanted to grab that instance…would i need to do that within an Event? or could i set the instances in a plain method?
Instance of what?
The Entity. In this case we’ll say it’s a creeper. So i’d code it as
if(entity.getType().equals(EnitytTypes.CREEPER)){
Player p = m.getTarget().get()
BlockRay.from(m.getLocation()).to(p.getLocation().getPosition()).skipFilter(h -> h.getLocation().getBlockType().getProperty(PassableProperty.class).map(Property::getValue).orElse(false)).build().hasNext()
So how would i get the above then to work?
I’ve probably butchered this…I’m sorry
That was example code. You’d replace ‘m’ with the name of the entity (in your code, looks like it’s entity
).
Ok. I see where’d you’d be going with that. then would it need to be within an event listener? or could it just be in a regualar method? I’d want this to always happen when ever say creeper targets something.
Code is code is code, it doesn’t matter where it is. If you have an entity, that code will get whether it has a block between it and its target.
K so it won’t let me use .getTarget on EntityTypes
That’s because EntityType does not have a getTarget. EntityType is a type of entity. You need an Entity’s target.
Sorry says getTarget is undefined for type Entity. I worded that wrong.
Oh, cast it to Agent first.
…and may i ask how that’s done?
uh
((Agent) entity).getTarget()
if(DayCounter.getWeeklyConfig() == 1){
if(spawnedEntity.getType().equals(EntityTypes.CREEPER)){
if(spawnedEntity.getType().equals(EntityTypes.CREEPER)){
Agent m;
Player p = (Player) ((Agent)m).getTarget().get();
BlockRay.from(m.getLocation()).to(p.getLocation().getPosition())
.skipFilter(h -> h.getLocation().getBlockType().getProperty(PassableProperty.class).map(Property::getValue).orElse(false)).build().hasNext();
}
}
}
K so I’m asking if you could look this over. Would this work for the Mechanic?
I know you asked me to stop saying this, but you should really learn Java more. A lot of your issues come not from a misunderstanding of the Sponge API, but of the Java language itself. Look at what you’re doing here. You’re putting null into a variable, and then calling a method on it. That’s pretty much the most explicit way you can throw a NullPointerException.
Because you’ll ignore the top half of this message given what it starts with, I’ll answer the question anyway. If you call a method on null, it throws a NullPointerException. Casting something simply changes what type your code thinks it is; it’s a core part of object-oriented programming. It won’t make an object appear out of nowhere. What you are meant to be casting is the entity itself. I assume from your code it’s the spawnedEntity variable. In fact, you could just as easily cast it to Creeper, which extends Agent.
The rest of your code would work perfectly, though I would point out a couple of things: You check the entity’s type twice, this is pointless. So is if (a == true)
; the if
statement uses a boolean value so if (a)
has the same result.
There’s also the fact that an entity will almost definitely not have a target when it spawns. Instead, I’d recommend listening to AITaskEvent.Add
and checking whether event.getTask()
is an AttackLivingAITask
.