#Thread
1 messages ยท Page 1 of 1 (latest)
ok
did you !verify in the channel?
If you did reconnect
reconnect to the website?
to discord
i did its kinda glitchy
Yeah sometimes its blue sometimes white
That usually fixes by reconnecting to discord
better
id is teh UUID field
I just copypasted all this except the player
yep, use id
thanks
hoveringArrowUsers, delete
I also got this
alright
DataHolder::new
yep
I was going to lambda, but instance is better
replace new DataHolder... with DataHolder::new
Like this
yep
I got this in my listener on right click air
Yeah, I should remove the hoveringarrowusers line entirely right
Yeah i got checks for it
teh DataHolder is all about that specific user so no need for it
I should add the code for the homing arrows to startArrow right
Should I put Player player = Bukkit.getPlayer(id); in every method or can I just add it outside all the methods so its in scope for everything at once
If you are goign to remove the players dataHolder reliably on disconnect you can hold it in a field
Alright
Should I put the stuff outside the bukkitrunnable in the addTarget method or does some of this code need to be in my listener like the raytrace
you rayTrace in your Listener, then pass the hit entity to your DataHolder#addTarget
does your arrow start flying the instant it gets a new target?
well, you could rayTrace in your addEntity I guess
just logic in yoru Listener to see if you need to raytrace
probably cleaner
On leftclick if it gets a target & all ifstatements are correct it goes to the homing code, then onhitentity if it still has a target it goes to the next target, and if it doesn';t have a target the player becomes the target and it returns
in that case all that code should move into addTarget
BUT
only start a new Homing if there is not one running already
the new homing starts on hit entity, and on hit entity the homing is at its location so its done
that code you showed starts a new task every time an entity is targeted
you shoudl only start it once, if not already running
if (homingArrow == null) homingArrow = new BukkitRunnable...
I'm correct in thinking (like Guardians) the arrow flys to each target in order.
Yeah
ok
i fixed this line by adding getuniqueid
targets.add(rayTraceResult.getHitEntity().getUniqueId());
done
as you are doing the raytrace in the addTarget you shoudl also change the method to not take a UUID
it will find the target now, so doesn;t need one passed to it
yes, its needed there
Do I need to make a new pasttargets thing just like players and targets
you can ignore the warning
you already check for null earlier
oh actually you don;t check for null
do i wanna change to like this but for pasttargets
Once a target is hit, or actually even a mob that wasn't a target, it gets added to past targets so it can't be added to targets again
for what reason?
The arrow glitched if it went to the same target twice and this was an easy way of fixing it, and I also want to be able to count how many mobs it hit so I can increase the damage if it hit more entities and decrease the cooldown if it hit more entities later on
What do you suggest I use to replace pastTargets? as I remove the 1st target from the targets arraylist everytime an entity gets hit so I can't use that to count how many it hit before
a simple int counter
later when you add a hitTarget method you can increment the counter in that
Alright
So for now i can remove this check and everything to do with pasttargets in the dataholder
yes
I can't use this anymore to get the first target in the arraylist as its a Set now
if (!targets.isEmpty()) {
UUID id = targets.iterator().next();
Entity entity = Bukkit.getEntity(id);
if (entity == null || entity.isDead()) targets.remove(id);
}```
its a UUID remember, not an entity
I got this now but I think i'm doing duplicate ifstatements & the geteyelocation sentence & the one above is probably wrong
I'll remove the highest if statement
and replace player with id
oh wait nvm
i just need to assign something else to target
got this now
at the very top you should have an if(targets.isEmpty) { this.cancel()); return;}
delete the line UUID target = (id);
add a return; after the targets.remove(id)
then move your lower code in the code block after
err
what is this doing?
isn;t this supposed to fly the arrow around all targets?
these 2 lines is the calculation to fly towards the target, and cause its a runtasktimer it will keep going when the target is changed
ok I was wondering why it was called a returnVector
Oh its cause I had it at the return calculation and then copypasted it to this one aswell i should change it
move those two lines in after java targets.remove(id); return; } ...
use entity not id
to get the vector
yep, but you needs to cast to LivingEntity not Entity if you want eyeLocation
we can check in teh addTarget if it's a LivingEntity before adding
looks good
i got no more errors in this class but I still need to add code to stopArrow and stop the hovering arrows
alr so i also wanna make a stopHoming method
nope
oh
you only start homing when adding a target if homing is null
so you can stop it and set to null when it runs out of targets
setting to null is the signal to the addTarget code it should start a new one
yeah but when it runs out of targets i first need to add the player as target so it can return and then i made it so when it hits the player everything cancels
So i will make a return method now and add my return code in there
in the return on empty you instead add your player UUID
let the rest of the code run
then when it hits the player it will be passed in as a hit and you can cancel/set null there
yeah
the player will just be treated as another target, so that codes done
but I still wanna make a new method right cause now the arrow will only home to 1 target, I have in my onProjectileHit method the code to go to the next target on hit and remove the old target
this is my old code to remove old target and go to new
well once we add teh hitTarget code
now it sems time to add a hitTarget(Entity entity) method
alr
public void as always
in your event you shoudl dojava if (getHitEntity != null) players.forEach(holder -> holder.hitTarget(event.getHitEntity());
Shouldn't I call the stopHovering arrow method & startHoming method at the point all the code was at first like this
in my listener
your arrow should always be hovering (when active) unless homing
like this?
just cancel it anyway. it doesn;t matter what state it's in
um
no
do it yoru way, check first
as Tasks can throw not started errors if you try to cancel an already cancelled task
So I don't need a stopHovering method as I can just write hoveringArrows.cancel();
yep
Alright and I'll keep the starthoming method in the listener and it will automatically cancel the hoveringarrows in there
Now i will do this i think
yep
oops i forgot this
or do I wanna put addtarget inside the starthoming method aswell
alr
perhaps not, you don;t want it to stop homing if no target was found
yeha i'll add a check
start you mean right?
yeah sorry, you stop hovering, start homing
i got this at the bottom of addtarget
I just noticed I also cancel hoveringArrows here
yep, alls good then
so I can remove the check in startHoming
cause startHoming is called at the same moment the hoveringArrows is cancelled so its allways cancelled at this point i think
yep
Alright now I will do this
I put what you said in my event
that will be seen once you add teh hitTarget method in your data class
Alright
I did I just didn't add anything to it yet, I will just put everything in my onProjectileHitEvent in there except the first check
Do I need to keep my ifstatements where I use event. in the listener?
which one?
I have a lot
I should make a method for everything under a event.getHitEntity ifstatement right?
This all too?
all that is now in your homing task code in yoru data class
Yeah this is to switch between targets and make it home to the player when its empty
Alrught
How about this?
this is the code to clear everything that needs to be cleared and change the ghasttear item to an arrow again when it hits the user
that will all be moved into the hitTarget method
so I comment it cause I still need it later, not remove? and the screenshot above that can be removed
yep
this is all i got rn, the stuff with pastTargets is to make a damage combo so u deal more damage when u have more pastTargets
I can also remove that right as I need to rewrite it cause pastTargets is gone
past targets will be changing to a hit counter in the data class
alr i'll just comment it too
This is all I have rn, the last check is so the player doesn't take damage but I have to comment & uncomment that to test damage withmyself
you change teh damage if hitting a player?
Honestly idk what to write in hitTarget now cause you say it will already cycle through
Its cause I made the damage higher for mobs
ok, we'll ignore any change for a player for now
we can set that later
lets focus on processing teh hit
Aight
in the hitTarget methodjava if (!targets.contains(entity.getUniqueId()) return;
so we ignore it if it's not one of our targets
got it
I added Arrow arrow
ok
oh, if the target we hit is the first in our Set, we remove teh target
ok
targets.remove(entity.getUniqueId());
if (targets.isEmpty()) {
if (entity.getUniqueId().equals(id) {
//We hit ourself as the last target so we are home.
return;
}
targets.add(id)
}```
we also need to add our counter now
but, lets get this working first
Alright i got it
yep
in that part where we hit ourself, we should cancel the homing task, set it null and start the hovering task
This is what I had before btw for reference https://www.youtube.com/watch?v=5pfvxUIvP04
cause I didn't update the code in my server yet
Oh i still got an related problem with this
it works in this bottom sentence tho
I can't use .getValue on holder
one sec
forEach((k,v) -> v.hitTarget
would probably have been simpler to just value it
players.values().forEach(holder -> holder.hitTarget
I still have all these things at the top
don;t use that
remove them all?
get teh projectile from the event
except dataholder
So I should make a getter for flyingYakkaArrow?
no
you only need to compare the player arrow to the projectile in the hitTarget method
uh
pass the event.getProjectile()
that doesn't exist
its probably getEntity()
change the arg in the hitTarget method to take a Projectile
i did ๐
Oh but I can't properly check if its the right arrow now
As I make the arrow flyingYakaArrow so i can't check if it was flyingYakaArrow before
do you need to check it?
I mean otherwise any projectile that hits the target will be seen as flyingYakaArrow right?
not in any of the data class code, as it will compare to the actuall arrow you spawned
but
what version of Spigot are you building for?
what is the oldest you need to support?
Uh i'm coding for 1.20.4 but idk which version of spigot i'm using
ok after that dojava flyingYakaArrow.getPersistentDataContainer().set(new NamespacedKey(YourPlugin, "yaka"), PersistentDataType.INTEGER, 0);
Oh to give a key smart, my arrow and ghasttear items have keys already but i didn't do it for the flyingarrow
you can also use this to increment as a hit counter
so in your hit code just check for the PDC key
oh yeah a key I also forgot xdd
you can now early return in the hitTarget method if no PDC key
I think i'm doing something wrong
one thing I'm not sure we covered was if Bukkit.getEntity(UUID) returns null in teh homing task. We shoudl remove the target from our Set
new NamespacedKey(plugin, "yaka")
no
so that event is done?
not toohard
I should probably put this in the dataholder too right
this is so you can change the ghasttear back to an arrow
if you right click
and everything will cancel
//onQuit
DataHolder holder = players.get(event.getPlayer().getUniqueId());
holder.quit();
players.remove(event.getPlayer().getUniqueId());```
add a quit method to teh Data Holder to cancel either task if running and remove the arrow
you don;t need to change any damage values as teh arrow is created new
Also I should probably make a new Player player; at the top right
cause since I removed it all my players don't work
yes
and just change every player to .getUniqueId
damn elgar it's been lik 5 hours and you're still going
Make sure to reuse your variables!
i didn't think it'd be so hard to make it compatible for multiple players, I thought it would be a case of changing some names
Why haven't we made a manager class yet?
elgar's been spoon feeding for the past 5 hours
a fair bit, but he's understanding it
I already have if you mean this
tags?
I mean its a key I just called it tag
ah ok, yep
you should check for that PDC rather than comparing material type
else any ghast tear can be used
I already check for that at the start
Yeah i think i haven't changed it to the right id playery et
if you have you can just call quit on their DataHolder then
and remove them from the map
I just copypasted it but I still need to change some stuff
like imma re3move the player check
player already exists in yoru DataHolder, so use thaT
delete all pastTargets stuff
and no need to change damage at all
no users anymore either
Should I add the check if its the right player in the quit method or quit event
but I don't wanna remove stuff for players that didn't use the arrow right? won't that be a waste of resources when I have a lot of stuff that needs to be removed on quit
after calling homing.cancel() you shoudl also set it null, just so you won;t have any issues if you forget to remove from teh Map at any time
teh quit method doesn;t remove any items
it only removes the arrow entity and stops any tasks
yeah
but then the code will run for everyone thgat quits I thought i wanna limit it so it only prcs when someone who is using it quits
it only runs for the player who is quitting
cause imma remove everything also when they turn their ghasttear back into an arrow
yes but i never hcecked for this player
you do in the quit event
you get the player from teh event and only run their quit code
event.getPlayer().getUniqueId()
I don;'t have any if statements so I don't really understand how I'm seperating the arrow users from all other players that quit
because you are forgetting each Player has their own DataHolder
you only call quit in teh DataHolder for that specific player
Instances can be confusing
just because there is only one set of code, it's per instance not per class
Should I replace these with the same code in the onQUit method or create an onDisable method so I can also disable the hovering arrows in there and basically copy the onquit
Yeah but I also need to disable hoveringArrows in there
use the same code you use in onQuit event
or I can just add removing hoveringArrows to onquit
Alright
i got no more errors ๐ฅน
imma test it, but i can't test it with multiple players cause server.pro doesn't work anymore so i gotta find something to make a server quick
Also idk if the "player" I use in my listener is the UUID player as I assign it like this
oh the first interact event doesn't work yet
Yeah I'm not good with object instancing like that, which is why I prefer lambdas
one sec
ok try computeIfAbsent(player.getUniqueId(), k -> new DataHolder(k));
I get the same error
also if I click on replace its the same sentence as before so thats why its the same error
@brittle horizon Why does this error?
can't use DataHolder::new as it needs a UUID
show me your whole DataHolder class
It's a function so k -> new DataHolder(k) works as long as k is the same parameter type as the constructor
and k -> new DataHolder(k) is the same as DataHolder::new
Replace will work
something tells me your IDE's just bugging out
Try seeing if it compiles
full line
Fun
Something tells me this is the caused by part
The map would error a lot sooner than DataHolder does
I'll need the full stacktrace
My bets are on the Bukkit.getPlayer method being called before id is init
Post the whole thing
fun it's pointing to an empty line
ah
yeah it's his Field of Player inj teh DataHander
I'd refactor this code to not be leak prone
Why are we storing a player field in the first place
public Player getPlayer() {
return Bukkit.getPlayer(this.id);
}
I'm middle of dinne, but I did say no tto store a player, get it when needed
Store it as a local variable on every method when needed
Same for all your entities
You have the UUID so just get as required
I'm gonna go on a lil walk and have dinner with my homie gtg
bye have fun
If i'm understanding this right I should remove this and paste it in every method where needed Player player = Bukkit.getPlayer(id);
well, you can have a Player field, but you have to set it in the constructor
so the field would be Player player;Then in the constructorplayer = Bukkit.getPlayer(id);
in the parameters of the constructor or inside?
under this.id =
yes
I can pass the interact event now but the flyingYakaArrow doesn't spawn properly
no errors
I can hear the dolphin sound so it gets till there i guess
Maybe I should also add the flyingYakaArrow entity like illusion said
oh but it doesn't spawn when I rightclick
as you create it you can store a reference to it
does anything happen when you right click?
yeah I hear the dolphin sound on line 63
I can add debugg messages inside the runnable to see till where the code runs
I have no idea what line 63 is, so
on the left in the last screenshot
ah ok, the playSound
I see why
oh
thats automatic when you make a bukkitrunnable
implement methods
delete 66 and 95
Which lines in thsi screenshots as they moved aroudn a bit
line 70
yep
i didn't even add a delay to that runtask so it was there for no reason
That unfortunately didn't solve it but I'll keep it removed as it serves no purpose
yep
if you hear the dolphin sound then the code is running
teh arrow itself gets spawned very close to teh player (initially)
10cm from their eyes
I hear the dolphin sound but no arrow gets spanwed not even for a split second
its likely inside their head still
increase teh distance it spawns at
also add debug to ensure teh task is running
the task is not running i checked with printlns
where did you add teh debug to check?
under every if statement & inside run & inside new runnable
but I think I know what i messsed up
very stupid mistake by me/ rookie mistake same thing
i disabled everything in the wrong event
๐
it works now
excellent
but when it hits a target it doesn't go to the next yet
does it get destroyed?
no
it keeps flying at the spot of the entity
And if I move the entity it follows it and glitches on its head
Check if this is returning by mistake
I added all of these debug messages and none of them trigger
Also while the arrow is flying to the 1st target, if I click on the 2nd target redirects, instead of hitting the 1st target and then redirecting to the 2nd target like before
have you forgot to delete an arrow field in your Listener?
what?
I only delete stuff in on quit, on hit yourself and on right click
oh i see something else that happens now
while the arrow is glitchin in the head of an entity
if I click on a new entity it goes towards it
but only once
only once?
wait sometimes more
delete line 30 in your Listener Player player;
i did now 9 "player" 's need something new
line 45 becomes Player player = event.getPlayer();
ah line 85 has an error
once its stuck in the head sometimes it can go to a new target sometimes not
players.values().forEach(holder -> holder.hitTarget(event.getEntity(), flyingYakaArrow));Should beplayers.values().forEach(holder -> holder.hitTarget(event.getHitEntity(), flyingYakaArrow));
I think
yes
its currently passing arrow and arrow
a step further it doesn't glitch anymore
but it also doesn't return
and it goes through the targets in the opposite way
yeah, if I click on 3 golems before it hits one, it will go to the last golem I clicked on then the 2nd to last then the 1st
its right just the exact opposite order, but it doesnt return yet
after the last one?
no attempt at all to fly to the player?
oh sec I see it
just the order now then?
in the DataHolder change from a HashSet to LinkedHashSet
that will preserve insertion order
yeah, and then i'll change some small things I think are within my skill level
in DataHolder delete private Map<UUID, DataHolder> players = new HashMap<>();
should not be in there at all
I also added this line as when it returns the arrow keeps flying behind me instead of deleting
yep
and in the projectile hit event I will add an else under this that despawns everything and gives the arrow item back as that means it hit a block
yep
Although there is no "event.getPlayer" as its an projectile hit event so I'm not sure how to get it
well call teh quit method in the Holder and give an arrow back
projectile.getShooter()
but there is no shooter
if you set it when you spawned it
as I don't use a bow
set teh shooter when you spawn it
when you spawn
yep
for the first part I need to use ProjectileSource and the 2nd part I need to use Player to send a message so idk
if (shooter instanceof Player player)
Thanks got it
Almost everything works like before and I think this will work with multiple players. I think I'll be able to figure out the rest until its exactly how I like it, thank you so much. I don't know how I can thank you enough for spending all these hours helping a stranger but I am super grateful โค๏ธ
np it was fun ๐