#help-development
1 messages · Page 874 of 1
i guess i could hack into the hypixel database?
for some reason I actually doubt that
ye gitlab probably way more
Shhhhh
imho the only real issue with bitbukkit is its a bit annoying you can't see PRs if you haven't signed CLA, otherwise its fine unless you want to integrate CL/CI
I wonder whose genius idea it was to group view and create together lol
¯_(ツ)_/¯
tbh I dunno what gitlab's permissions are
I checked the other day, it has separate create and view perms for pull requests
Sorry, “merge requests”
ideally you'd also not want comments on PRs except for people that can create them either
maybe comments are seperate too
I don’t see a perm mentioning comments
But apparently you can lock a merge request to limit comments
“You can prevent public comments in an issue or merge request. When you do, only project members can add and edit comments.”
only thing I see is this, but not sure it does tbh
Ah that might be it
I think thats for projects
Yeah but the comment page doesn’t say you can add comments to projects
that's kinda weird
you'd probably have to just spin up an instance and check it out yourself
someone set it up and test kek ¯_(ツ)_/¯
you can
Technically it’s also OS so you could make your own perms in theory
yeah but that is +1 thing to maintain lol
just dont update /shrug
Ah yes
git md
@remote swallow I am slaving away in documentation land
sounds like ur having fun
Ah yes gitlab uses the best language
php
Ruby on Rails
ruby off rails
@remote swallow 1 step closer to tearing PineappleChat out of Pineapple
ill do the versioning when u finish it
I still don’t understand why the ruby is on rails
it makes it faster
I hope they are powered rails then
i wanna rob josh on an mc server but hes ran away
because i fell asleep at 5 pm bc you didnt respond in dms
classic early morning vibes
what time even is it for the md
now get on wynn
3:45pm
sleep is temporary, the glory of leveling up your class is also temporary but more satisfying
i was about to say do you not have work today but its saturday
australian time gap is wild wtf
its only like 11 hours for me to md
its 17 hours for me 💀 you can imagine that makes it hard to play games with my australian friends
wait if I did my math right
lol
one sec
this is so much more annoying with 12 hour time
yeah 17 hours
16 here
EST nerd spotted
"yo man can you do this ill be back in 12 hours for 5 minutes bye"
Anyone here that knows about the WorldEdit/FAWE API?
Want to know how to retrieve the changed blocks by an operation
@remote swallow how do you make a drop down in mark down
uhhhhhhhhhhhhhhhhhhhhhhhhhhh
so turns out gitlab is the same
like code?
there's no view-only merge request permission
this perm doesn't exist? or does it just not do what it says it does
doesn't seem like it
Do you also have the view merge request list set
I'm only tinkering with Settings-> General and Manage->Members
@eternal night 😨 your gitlab dream might not come true unless you can find that permission

also custom permissions at all are gitlab ultimate tier
they've really kneecapped the open source version
lame
wow that is ancient
we don't take PR for Bukkit afaik
if it is still an issue remake the issue on SPIGOT
they're private for a reason BUKKIT is nolonger maintained idk how many years you've been away, but
spigot maintains bukkit thus all reports should be made to the Spigot bug tracker
under the SPIGOT project
best you could do is email support, but I doubt they'll be unprivated
?support
Hi im trying to learn listener, so im actualy reading an opensource plugin But I have a question that I can't find an answer to.
They have a Event call "FishEatEvent"
private static final FishEatEvent eatEvent = new FishEatEvent();
public static FishEatEvent getInstance() {
return eatEvent;
}```
And they register the event like this: ```registerEvents(FishEatEvent.getInstance(), this);```
I don't understand why they use an instance ? I have always register my events like this ```registerEvents(new FishEatEvent(), this);```
Is there a reason why he uses the instance to register the event ?
I mean IG technically its a singleton
that's kinda a werid practice for events though
There really is no difference or benefit to that method even though an event is "technically" a singleton it's a bad practice for events imho just register your events as you have been doing
Alright thank u for the answer 🙂 !
No we never had BUKKIT issues
It's a reference to the bukkit bug tracker which is way dead
We never had anything to do with it
holy old then
^
bukkit is a dead project so you'll be hard pressed to find anything
best of luck :P
Usually this helps for me: Go to project settings, then modules, then add your projects folder as a module
sames prob going to happen to spigot after a while when paper hardforks
Time to PR this shit

Or, yknow, a CLA bot
(my offer of writing that one myself shall stand eternal (or use third party stuff like https://gitlab.com/gaia-x/lab/gx-cla-bot)
Tho ought to agree with md, they be gutting the OSS version of gitlab
What's that?
that one website that reposts everything stealing peoples downloads and ad revenue
how would I only show a player the silhouettes of other people?
like, invisibility but you can see player silhouettes
do they all need to be on one team? since that would break some of my current logic
Pretty sure that's the only way to get that functionality
mm that sounds like a pain to keep track of
how so?
looks awesome
Like
a hashmap should do it
Well maybe
because you need to keep track of the lifecycle thing
shouldn't be too hard to do
Just annoying
i think so, but you can just tick a linked hashmap
if you're using some BlockPos or Vector variable you need to keep track of worlds
how does that work
if it only has a location internally should be fine
if it has a world tho it's leak prone
okay yeah
basically if for whatever reason you don't manage to remove a block from the map
let's say because of an exception or concurrency issue
and the world ends up unloading
(let's say someone's running mythicdungeons or something)
ahhh i see
the world will still be in memory because there's a reference to your block
Location is safe after 1.13.2
If your plugin supports ancient versions I'd recommend making a BlockLocation wrapper class that just stores the world id and xyz
same thing happens if you have a hard reference to any Entity
which is why we blow up at ppl and tell em to store UUID instead
i just use UUID for entities yeah
same for any tile entity etc
i know they get invalidated pretty easily but in my mind Block was always safe to use for that
anything world related is prone to world related leaks
a fun one I've seen was having a Player reference in a task
For example let's say I do something like this
https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/world/WorldUnloadEvent.html what about this?
declaration: package: org.bukkit.event.world, class: WorldUnloadEvent
and just removing blocks if the world is this
that'd be good practice
ive accidentally done that too lol, ended up with identical exceptions to when you send a player packets async so it sent me on a completely irrelevant search. ended up being due to a mistake i had made 3 years prior
@EventHandler
public void onQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
Bukkit.getScheduler().runTaskLater(plugin, () -> {
if(player.isOnline()) {
return;
}
myPlayerManager.unloadData(player.getUniqueId());
}, TimeParser.parse("5 minutes").asTicks()); // my own utility stuff
}
This isn't exactly a leak but it keeps the player instance alive for longer than its scope intended
yup
when enchanting an item, the enchantments are generated server side and not client side right?
yeah
But we can fix that code by refactoring it a bit
so if I modify spigot source I could disable a specific enchantment?
@EventHandler
public void onQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
UUID playerId = player.getUniqueId();
Bukkit.getScheduler().runTaskLater(plugin, () -> {
if(Bukkit.getPlayer(playerId) != null) {
return;
}
myPlayerManager.unloadData(playerId);
}, TimeParser.parse("5 minutes").asTicks()); // my own utility stuff
}
you could also just remove the enchantment during the event
i know java but I never wrote a plugin and havent looked at docs, wanted to ask here first before I open anything
And now this is "safe"
you can listen to PlayerItemEnchantEvent (i think its called that) and remove the enchantment from that event
might also want to do the same to PrepareItemEnchantEvent in case the enchantment is in the enchantment offers

why not use TimeUnit instead of TimeParser
my time parser lets me pass complex strings
:)
Like 5 minutes 30 seconds
or 5m 30s
mhh fair
is there a way to only allow certain players to build, Interact etc in a chunk or like do I need to go through all block and then do a list
merci becoup
https://snipboard.io/NlgXhF.jpg
how do i pass in the player to this
im not the most advanced java developer
?paste
Player player = (Player) sender;
Its called a cast and needs to go after the instanceof to prevent an error
I'd also advise using teh LuckPerms API over sending console commands
In newer java versions you can also do sender instanceof Player player
oh i looked at that first but decided against it as i have been coding in java for a total of 2 days :)
So does this look about right or absolutely not https://snipboard.io/8znZPS.jpg
no
Please post full code
I have quite a few questions
is there a player variable?
More active supporters, can anybody tell me wtf is going on
No cast needs to be between line 30 and 31
you cast before you check its a player
im getting red squigly line with that
hover over and see what it says
ah thats because your saveInventory method could throw an exception you are not dealing with
you will get that warning even using a player variable
You need to handle your exceptions with a try/catch block
Your IDE probably offered you to either add a throws or a try/catch. You chose add a throws
so do the try/catch
wait no i think thats what i did
idk
https://www.spigotmc.org/threads/save-inventory-and-then-load-it.43907/
the code im using is Shadow48402's reply
No I want to make certain chunks only usable for certain players so player1 can build, break etc but player 2 cant do anything there
bro i wish minecraft was fucking python
easiest shit going
It would be hella slower
Oh hell nah
yea
Already quite slow
😆 im joking guys
Tps'd be limited at 10
Fuck python actually
WOAH
He got us
thats a bit codist dont you think?
You are just throwing a pointless exception in your try/catch instead of dealing with the actual exception
nah, python's good for small applications which aren't too complex
Those are called scripts
Python is good for scripts for which sh is not enough and a proper programming language is too much
idk, I only learned python like 1 year ago and only now we're starting with it in school xd
ive been on discord longer than md5.
Damn
md5 and a lot of others came from IRC 😉
Mojo seems a better alternative to python but it isn't released
that was before i was probably born
probably, we've been at it a while
According to trivia, perl is like a common language to script in linux or something
If u are not above 16 u could've gotten banned when u started this acc
depends per country
i am 16. i still could've ggotten banned when i started this account
my fucking shitty code and my shitty error handler wont explain fuck all
any suggestions
instead of hiding the error behind a message, use e.printStackTrace()
teh stack trace will tell you the actual error
Make it deOP when you go offline and add a password to make the command work so if your account gets hacked they cant mess up your server
yeh i could do that, but for now im trying to make it save/load the inventory
where shouldl this print. console? or in the chat
it will print in the console
ok
perfefct
! [Sat 11:31:34 WARN ] java.lang.NullPointerException: Cannot invoke "org.bukkit.plugin.Plugin.getDataFolder()" because "this.plugin" is null
ok i believe this is my fault
llmfaoooo
now where is the this.plugin
Plugin plugin;
public void saveInventory(Player p) throws IOException {
File f = new File(plugin.getDataFolder().getAbsolutePath(), p.getName() + ".yml");
if (!f.exists() && !f.createNewFile()) {
throw new IOException("Failed to create inventory file for player: " + p.getName());
}
FileConfiguration c = YamlConfiguration.loadConfiguration(f);
c.set("inventory.armor", p.getInventory().getArmorContents());
c.set("inventory.content", p.getInventory().getContents());
c.save(f);
}
plugin plugin im guessing
is what i need to change
?di
Guide to dependency injection: https://www.spigotmc.org/wiki/using-dependency-injection/
Here are some links to get you started on learning Java:
- https://www.codecademy.com/learn/learn-java
- https://www.sololearn.com/learning/1068
- https://www.learnjavaonline.org/
- https://programmingbydoing.com/
- https://docs.oracle.com/javase/tutorial/java/index.html
The last one is the only official one, however some of those concepts assume that you already know a bit about programming.
would help you
with all due respect, i aint readin all that
With all due respect, I an't helping you further
okay chat gpt fixed my issue in a matter of 2 messages
and do you know what the issue was
thank you all for NOTHING (other than ElgarL, and md_5)
Yes, chat GPT explained it very nicely
Understood, let's resolve the NullPointerException issue by ensuring that the plugin instance is properly passed to your AdminToggleCommand class. Since you have no experience in Java, I will provide the complete revised code for both the AdminToggleCommand class and the way you should initialize it in your main plugin class.
Here is the revised AdminToggleCommand class
buddy. (period)
yeah that can be explained way better
In 2014 during a schizophrenic BPD episode, I spent $492.63 on Candy Crush
ill ask chatgpt to do that for me
holy shit

that's a lot
In the domain of software engineering, particularly within the confines of object-oriented programming and design patterns, the modifications introduced to the AdminToggleCommand class encompass the instantiation of a constructor that mandates an instance of the Plugin interface as an argument. This constructor invocation is an embodiment of the Dependency Injection (DI) design pattern, which is a subset of the broader Inversion of Control (IoC) principle. By employing this pattern, we facilitate a decoupling of the command class from the instantiation logic of its dependencies, thereby promoting a more testable and maintainable codebase.
This DI pattern is implemented to inject the requisite Plugin instance, which is essential for accessing the filesystem path associated with the plugin's data storage directory via the getDataFolder() method. By ensuring that the Plugin instance is non-null at the time of the AdminToggleCommand object's creation, the design precludes the occurrence of a NullPointerException. This is achieved by the strategic placement of the command registration logic within the onEnable lifecycle method of the main plugin class, which is derived from the JavaPlugin abstract class provided by the Bukkit library.
Furthermore, adherence to the Command design pattern is observed, wherein the onCommand method encapsulates the execution logic pertinent to the administrative role toggling functionality. This encapsulation is pivotal, ensuring a singular responsibility principle (SRP) is upheld, thereby aligning with the SOLID principles of object-oriented design and contributing to a robust and scalable software architecture.
To instantiate the AdminToggleCommand with the correct state, the client code—the JavaPlugin subclass—must pass its this reference (which in Java signifies the current object instance) to the AdminToggleCommand constructor, effectively passing its own instance to the command handler. This operation is intrinsically linked to the polymorphic nature of the JavaPlugin class, ensuring that the specific plugin instance is bound to the command at the point of registration within the plugin's command map. This process is crucial for the Bukkit framework to correctly route command invocations to the associated executor with the appropriate context and state.
Good enough for you, @remote swallow ?
(This message was AI Generated.) by the way(). HES LITERALLY ON MY PAYROLE - DO NOT DISRESPECT! ( im paying him $60 a month. Team edition.)
I have a feeling this is getting off-topic and unnecessary
sorry.
well to be fair it is compleltely on topic, unnecessary, yes. on topic? yes.
Just fix your issues if you are able to and if you aren't just ask here
Heyo
InteractEvent gets called when player drops an item.
This is easily solved by storing the uuid of a player in a list on PlayerDropItemEvent and then checking if the uuid exists in PlayerInteractEvent
BUT
When a player drops an item from inventory, the events are called in reverse order, so this hack doesn't work.
Any way to solve this stupid problem ?
I was going to use GPT 4 to help you, but i reached my quota.
hey guys, is there any way to fully disable a player from using a command? even if this command would usually activate code in another plugin. supposing a plugin has a /etc command, could i fully disable players from using this even though it is stated in another plugin?
ad a permission to the command in plugin.yml
if they have no permission, they don;t see the command
how much smarter is gpt4
a lolt smarter. it basically helps with everything.
so i have to do this for each plugin individually? is there no simpler way of doing this?
no. i would like to warn you about the rate limited issues.
that is the simple way, and it's per command
ah ok. so i just edit each plugins config files and try find the command?
most plugins already configure a permission per command, IF they are written properly
ok nice, i'll have a try thanks
Hey, I finished my code for a custom item with an ability, but I assign the Player player; in my PlayerInteractEvent with " player = event.getPlayer(); " and keep doing stuff with that specific player the entire code with " player. "
The problem is that if 2 players use it at the same time, the 2nd player will replace the 1st player. I think I have to use UUID's but i'm having trouble using/understanding it
Can anyone please explain what to add to my code so it knows to use the specific player that completed the PlayerInteractEvent at the start, and if a second player uses it at the same time it will also work
Do not track by player, track the item itself
what specifically does your item do?
Its an arrow, when I rightclick it turns into a ghast tear and an arrow starts hovering infront of me, when i click on entities the arrow flies towards them in the order I clicked on them, and then flies back to me and turns into an arrow again
use a Set<UUID>
oh so like in guardians of the galaxy?
when a player activates you add their UUID to the Set.
then when using you check if their UUID is in the set and run your use code for them
exactly
Thank you I will try this
?notworking
"Does not working" is a useless statement. Please describe what exactly is not working, what you expect it to do, and what actually happens. If you get any console errors, also ?paste the entire stacktrace.
well, the statement is not working event.getCurrentItem() instanceof WixiCustomMenuItem wixiCustomMenuItem
You should instead track things with proper data structures
like?
Map<Integer, Whatever> on your menu class
this is outside of the inventory
not in the menu, it's in the player's inventory
while the menu is open
how can i execute a command from a non-op player as if they were op?
Then associate an nbt tag
how?
?pdc
how would an ItemStack ever be instanceof your custom class?
add a PDC to item and check if item has it
it extends ItemStack?
what would be the purpose of this?
A player can not execute a command as Op if they are not Op. You can run the command at console for them is all, but not as the player
well
what's PDC?
here's a super easy way to trip antimalware
once you add it to any inventory, it will not be instance of any custom stuff anymore
oldOpStatus = isOp
setOp(true)
runCommand
setOp(oldOpStatus)
this is correct, but this is poor practice lmao
or: Why you should NEVER use NBT tags again! Spigot 1.14.1 added the biggest improvement that (in my opinion) ever made it into the Bukkit API: The Persistent Data Container (PDC). It can be used to store custom data on Entities, TileEntities, and ItemStacks. Using a bit of math, it can also be used to...
yep but bad as commands are async, others could nip in the middle
generally, in most cases you don't need to arbitrarily run commands from a plugin for a player rather you can just do the action from the plugin
well not just that, just in most cases not necessary to do this
btw @topaz kestrel you are not supposed to extend ItemStack in the first place
we should make it sealed
spigot-api is java 8

Like this?
private Set<UUID> playerUUIDs = null;```
```java
@EventHandler
public void onInteract(PlayerInteractEvent event) {
if (event.getHand() != EquipmentSlot.HAND) {
return;
}
player = event.getPlayer();
playerUUIDs.add(player.getUniqueId());
if (!playerUUIDs.contains(player.getUniqueId())) {
return;
}```
And add the ifstatement to check if the player has the UUID to every event?
Why is the field null?
private Set<UUID> playerUUIDs = new HashSet();
oh thank you
Sets.newConcurrentHashSet 
remove them from the Set when you disable your feature
If 2 players use it at the same time will it work cause now the code will run if the UUID is anywhere in the set. Shouldn't I check if the player has the exact UUID?
you run it for teh player who is activating it
if they set multiple targets, you have to track targets for them
each would have their own set of targets
also what's the point of checking if the set contains the UUID right after you added it?
good question
iejava Map<UUID, Set<UUID>>
first UUID being the Players Id, teh second Set of UUID's being target UUIDs
public interface Setting<T> {
T getDefaultValue();
}
public class BooleanSetting implements Setting<Boolean> {
private final boolean defaultValue;
public static Setting<Boolean> create(boolean defaultValue) {
return new BooleanSetting(defaultValue);
}
private BooleanSetting(boolean defaultValue) {
this.defaultValue = defaultValue;
}
@Override
public Boolean getDefaultValue() {
return this.defaultValue;
}
}
public class PlayerSettingData {
private final Map<Setting<?>, Object> values = new ConcurrentHashMap<>();
public <T> T getValue(Setting<T> setting) {
return values.getOrDefault(setting, setting.getDefaultValue());
}
public <T> void setValue(Setting<T> setting, T value) {
values.put(setting, value);
}
}
public final class Settings {
private Settings() {}
public static final Setting<Boolean> WHATEVER_SETTING = BooleanSetting.create(false); // false by default
}
hm
couldn't you just do UUID for both key and value?
I mean map can give you a set from the map
he is setting multiple targets per player
oh right
public class PlayerTargetData {
private final UUID playerId;
private final Collection<UUID> targets = Sets.newConcurrentHashSet<>();
public Collection<UUID> getTargets() {
return Sets.copyOf(this.targets);
}
public void addTarget(UUID targetId) {
Preconditions.checkArgument(targetId);
this.targets.add(targetId);
}
public void removeTarget(UUID targetId) {
Preconditions.checkArgument(targetId);
this.targets.remove(targetId);
}
}
hm
This is how I add & cycle through targets if it helps
On leftclick
targets.add(rayTraceResult.getHitEntity());```
```java
LivingEntity target = (LivingEntity) targets.get(0);```
On projectile hit
```java
if (!targets.contains(player)) {
pastTargets.add(event.getHitEntity());
targets.remove(event.getHitEntity());
if (targets.isEmpty()) {
homingArrows.cancel();
targets.add(player);```
so using the Map```java
Map<UUID, Set<UUID>> targets = new HashSet();
// onInteract first time...
targets.put(player.getUniqueId(), new HashSet());
// adding a target...
targets.get(player.getUniqueId()).add(entity.getUniqueId()));```
elgar your 3rd line is error prone
probably get an add or put wrong there, btu you get the idea
computeIfAbsent
We love computeIfAbsent
he only wants it to happen if the player is active using the arrow
Should I change my current targets arraylist to a set?
private final ArrayList<Entity> targets = new ArrayList<>();```
i never understood why computeIfAbsent uses a Function instead of a Supplier
mine is just an example, so add if the entry is nt null
probably for functional stuff
if you want to only ever have one instance of a player in the set, yes
they should just have a second method
You needs a target List/Set for each players using it
think of it like
a set doesnt allow multiple instances of the same object
Set just prevents duplicates
If you have a constructor that takes your key as an argument
You can just do MyObject::new
I want my code to work for multiple players at the same time
ah yeah probably useufl in case you reuse the function you throw into computeIfAbsent
okay, but you dont want it to work on the same player twice, right?
Should I try elgarL solution or imIllusion solution or combine them
No only after the entire ability is finished and I remove everything at the end
Mine works for multiple players but needs an extra class for managing the map
Yours is super simple and beginner friendly while mine is foolproof and follows perfect etiquette
Well I should be making hashcode functions if that were the case
yep
Does this work if the target isn't a player? and I don't need to add targets at the first oninteract as its just to spawn the arrows hovering
yes, all entities have a UUID
I'm kinda confused, I tried your stuff at line 33 and 55 can you check
a set is not a map
and you also cannot "add" to a map, you can only "put" to a map
You have too much jank code in there to really tell what you are doing.
Start a new class
as each player needs their own target Set and arrow
I did
and i fixed this
As your players each need their own arrow, targets and task you should create a data holder class
Why are you using a ConcurrentHashmap for this? Are you planning to update the map in an async context or was it used preemptively for safety?
safety
Illusion is a concurrent hashmap simp
It's the impl I use by default
static methods don't belong in interfaces
And what should I add to it?
private Set <Map<UUID, Set<UUID>>> targets = new HashSet();
}```
It's not a static method ??
Well
The static constructor is on the creator class and just returns an instance of itself
I return it as the interface because there are no impl details that need to be exposed
It's a concept displayed in the Effective Java book
when you want to do something with the value
public class DataHolder {
UUID id;
Set<UUID> targets = new HashSet();
public DataHolder(UUID playerId) {
this.id = playerId;
}
}```
this class shoudl also have fields for your arrow
I don't think "DataHolder" is a good name through
why do we have a set of maps of sets
but it will do for now, he can refactor
Thanks I hate it
Tuple... i only use that thing for Discord4J and every time confuse my.. but only use Tuple3 xd
love tuples
is there any way of checking if a command was actually sent by a player, or the command was executed through the player using player.performcommand()?
https://pastes.dev/FfIb5YZe4F which ones should I define above and which below, sorry for being such a noob in this but I have no idea how data saving works and stuff
You are getting confused
each DataHolder is for a specific player
you will create one for each Player
it only tracks data specific to the owning Player
so, their Id, Their Set of target Entity UUIDs and their arrow
Pair and any derivation of it is programmatical garbage

Yessir
the arrow will only be known to/exist inside this data object
so like this https://pastes.dev/515HMrr33i
no need for arrows Set as each player will only have one
Kind of. Where are you trying to check this?
then add a public method so you can add a target UUID
public void addTarget(UUID entityId) {
this.targets.add(entityId);
}```
https://pastes.dev/0gN5OGeyLQ like this?
no need to pass in an arrow Id, you can do all this inside this class
each arrow will be specific to the Player so it's all inside here
in a commandpreprocess event handler
and why do you need to check it was called via code?
Is this all I need in the DataHolder class? https://pastes.dev/sozXu7mB7Z @eternal oxide
Only way i could think of is listening for incoming packets to see if a message, sent by the player, was the cause.
Command events don't fire when forcefully ran
perfect
ah ok, thanks 🙂
You could probably walk the stack trace
Myeah that works as well
I feel like this is the best option if true
Source: I've had to inject a custom command map to debug forcefully ran commands
using Unsafe or something

Now in your listener when a player activates their arrow.```java
Map<UUID, DataHolder> players = new HashSet();
// Player acitvates arrow
players.put(player.getUniqueId(), new DataHolder(player.getUniqueId());
// player adds a target.
players.get(player.getUniqueId()).addTarget(entity.getUniqueId()));```
DataHolderManager where? 🙂
You can add error checking later
lets not confuse him more 🙂
Meh
meh
public DataHolder getHolder(UUID playerId) {
return holderMap.computeIfAbsent(playerId, DataHolder::new);
}
hm
uh
The problem is
They are just getting too far ahead 🙂
what if we check that on a task after the player logs off
so we have to do some checks or scope everythin
Currently the aim is to get a working set of code, nbot to be perfect
too much junk code in there
Should I put this in a set or just add it at the topMap<UUID, DataHolder> players = new HashSet();
start a fresh clean class
oh its wrong link
Keep that one to copyu code from later, just start fresh
I meant to send this https://pastes.dev/kSElViItqs
It says Required type: Map Provided: HashSet for Map<UUID, DataHolder> players = new HashSet();

ok, next job is to ensure you only add a new Map Entry if they don;t already have one
Do I change it to this Set <Map<UUID, DataHolder>> players = new HashSet();
HashMap, not HashSet
oh

ok, next job is to ensure you only add a new Map Entry if they don;t already have one...
Do I want
Map <Map<UUID, DataHolder>> players = new HashMap();
or
Set <Map<UUID, DataHolder>> players = new HashSet();
got it Map <UUID, DataHolder> players = new HashMap();
Now you do whatever code you want to detect the player needing to add a new target
ignore arrows and all that for now
I can't use .contains
no, computeIfAbsent
public DataHolder getDataHolder(UUID playerId) {
return Optional.ofNullable(Bukkit.getPlayer(playerId)).map(key -> dataHolderMap.computeIfAbsent(playerId, DataHolder::new)).orElse(null);
}

what if you remove in that orElse hm
Do I even need to put this in an ifstatement
players.put(player.getUniqueId(), new DataHolder(player.getUniqueId());
}```
no
no .put
look at the link I just sent
you are simply replacing the word put with computeIfAbsent`
Yeah, more side effects is exactly what this method needs.
Sadly Map::remove returns the removed object
is there a computeIfAbsent for optionals
hm
I don't use optionals often
funny
the reason to use computeIfAbsent over put, is that using put will replace the Object every time. computeIfAbsent will only add it if it doesn;t already exist
ah thanks
calling put would erase any targets you have already set
I mean, you'd usually do .or
ifPresent is kinda ugly, you fall straight into callback hell with it
I wanna make the dataholder method public right
yeah, it's a cool way to do it quicker rather that recalulating the hash and position twice to achieve the same without
database method?
luka's just throwing stuff at the wall and seeing what sticks
what if we took a step back to learn the basics
do i wanna make a getter?
no
DataHolder(java.util.UUID, java.util.UUID)' is not public in 'me.luka.customitems.DataHolder'. Cannot be accessed from outside package
the constructor needs to be public
I removed it, i still need to make it public i think
no
you shoudl not be passing an arrow UUID into teh class and it shoudl not be asking for one
it shoudl have already been public
yeah my bad, I didn;t make it public in my example
you're good
Instead of going in circles for 2 hours let's learn java basics!
I learned a lot I just never used Set before and the UUID stuff is not java
Have you added your code to add targets?
also, how do your players deactivate their arrow?
Every time you call new you're creating an object and calling the object's constructor
not yet just reading through what you made so i understand it
ok
An object can have multiple constructors, the one you call matches the parameters you pass
Think of a constructor as a mandatory method that's called every time you create an object
public class MyObject {
public MyObject(int argument) {
// This is a public constructor
}
}
if there is no constructor you can just call new YourObject(). With a constructor it forces you to provide whatever it asks for.
Declaring a constructor is like declaring a method with no name, where the return type is the class itself
So if I try to call new MyObject() this will error out because there's only one constructor, and it requires passing a paremeter
Everything is clear so far, right?
I actually like this pastes.dev site
syntax highlighting, and so easy to edit live.
yea
Alright, now let's get to some data structures
but now i'm reading your stuff and trying to add it to targets at the same time i should probably just do one
You know List, right?
yeah
idk the difference between that and ArrayList but i know that I can store stuff in it and use loops to go through them
Alright
So a List has some order to it
You can add duplicate elements
get by index
I didn't know until today but now i kinda know it stores stuff but only 1 of the exact same type
A Set is basically a list, but has no obligation to know order, and won't take duplicates
So if I have a List<Integer> and I add(1) and then add(1) and print the list, it prints [1, 1]
I could get byindex from arraylist too
If I have a Set<Integer> and I add(1) and then add(1) and print the set, it prints [1]
ArrayList is an implementation of List
The same way HashSet is an implementation of Set
So the difference between a list and a set is clear?
Yeah, but not between a list and an arraylist or a set and a hashset but idk if its relevant to know the difference
Alright so we have to get on the topic of interfaces
for me it looks like it does the same
An Interface, in java, is basically a "contract" that defines expected behavior of a class
Think API and implementation
That's really easy to understand as someone proficient and really vague as a beginner
yeah true, but so is contract 😉
You can't directly initialize an interface (i.e you can't new MyInterface() as it isn't a class)
^ you can;t new List()
I probably know what an interface is I just don't know what I need to couple the name "interface" with but when I see it i probably get it
List, Set and Map are all interfaces
ArrayList is a class that implements the List interface
We call that "an implementation"
So ArrayList is an implementation of List
Oh yeah my friend said I cant do new with those things as they're already made by java, I also can't do new for something like Player as its already made by spigot
Well
Not necessarily
You can't new Player because Player is an interface and not a class
kinda. But really they are all Interfaces
So when implementing an Interface you're expected to actually implement the logic it demands
watch someone actually implement all the logic just to use fake Players
Yeah thats why I NEED to add something between the brackets when I use those
Yeah, I will try to not initialize interfaces in the future
Alright
Doesn;t go well 🙂
Moving on, we have Maps
In other languages they're reffered to as dictionaries
Where you have a Map<K, V> where K is the Key type and V is the Value type
So on a Map<UUID, PlayerData>, UUID is your Key type and PlayerData is your Value type
Oh thats why I can do "private Map<UUID, DataHolder> players = new HashMap<>();" but not "private Map<UUID, DataHolder> players = new Map<>();" as map is an interface and hashmap is a class that implements interface
correct
Yep
And key is always the thing its from like String, int, Player and value idk
List<?> example1 = new ArrayList<>();
List<?> example2 = new LinkedList<>();
List<?> example3 = new SortedList<>();```All lists, but different implementations
The Map interface defines a few methods, the more important ones are
boolean success = map.put(key, value)
V value = map.get(key)
V oldValue = map.remove(key)
There are some other ones like computeIfAbsent but most of those are just wrappers for these 3 basic ones
So let's do a basic impl
i forgot what ? does
any type
^ accepts any Object
Not good to use unless you are really experienced
alr
Map<UUID, Integer> count = new HashMap<>();
UUID playerId = UUID.randomUUID();
count.put(playerId, 1);
count.put(playerId, 2);
int result = count.get(playerId);
What's result?
it was just for example, less to type 🙂
2?
Correct
Now
Map<UUID, Integer> count = new HashMap<>();
UUID playerId = UUID.randomUUID();
int result = count.get(playerId);
What happens in this case?
null
nasty
Correct
it will actually throw an NPE as int can't be null
defaults to 0
You can;t assign null to a primitive
monkey
:(
does it matter, what matters is that it wont work
correct
Well not exactly as int is a primitive and primitives can never be null
there we go
yep
alright
But yeah for any object it'd be Null
so then 0, but yall said thats also not the case so it will just not work and give error
Yeah there's some autocasting trickery going on
You can worry about it at a later date
Regardless, keep in mind the following things:
Objects are kept in memory while they're stored in ANY collection (with the exception of weak collections, or when wrapped in a WeakReference - Advanced stuff)
And all the data they hold
So if you store for example a List<Player> and a player quits, that object will still be in the list
(which is a memory leak)
Make sure to invalidate your objects from whatever collections they're being held at if they're not meant to be valid
Can I just remove event.getPlayer from the list onQuitEvent
Yes
cool cause thats what I do for like everything that needs to stop workiung when u go offline
Never the less, good practice is to store UUIDs that represent these objects instead of the objects themselves
So for example instead of storing a list of Players, you store a list of all the UUIDs that represent the players
And you can get the player back from the UUID when needed
That just makes it so that IF you have a leak, that leak happens with as little data as possible
yeah this arrow was my first real plugin and I just focussed on getting it to work and learned a lot while doing it now I wanted it to work for multiple players and kinda hit a wall cause I never learned about Set or UUID and stuff
You are close now
Now, to tie it all together
its really just a case of moving code into your DataHolder and adding methods to start/stop the arrow
When designing your structure you need to know what relationships there are between your data
So in your example, you have multiple players, and each player can track multiple targets
So you segment it a little bit
Making a "player data" class that represents what a player tracks
And making a "data tracker" class that represents all the player data for all the players
Yeah and I only have 1 arrow per player so I don't need to store that in the same way as the players & targets, and the multiple targets are per multiple player so it should be below it or something
Basically wrapping a Map<UUID, Set<UUID>> in 2 classes
In that case it'd be a Map<UUID, UUID>
I'd still avoid being niche about your second argument and making a class for further expandability
in your case you have all the structure now
currently your Listener IS your "data tracker"
Even if it looks something like
public class PlayerTrackingData {
private final UUID playerId;
private UUID targetId = null;
public PlayerTrackingData(UUID playerId) {
this.playerId = playerId;
}
public UUID getTargetId() {
return this.targetId;
}
public void setTargetId(UUID targetId) {
this.targetId = targetId;
}
}
Your data tracker should be the one responsible for creating the data objects
I have this rn
public class DataHolder {
UUID id;
Set<UUID> targets = new HashSet();
public DataHolder(UUID playerID) {
this.id = playerID;
}
public void addTarget(UUID entityId) {
this.targets.add(entityId);
}
}```
thats your Player Data
Although in certain cases other classes can be the ones asking it to init the object
Your tracker class is basically just a Map<UUID, PlayerTrackingData> wrapper
What he is talking about is the function your Listener is currently doing, which can easily be moved later
With friendly methods to get a player's tracking data, set the target etc
Yeah my friend made everything in seperate classes and called the methods I'll do that too later but I just want everything to work in 1 class first
how do your players stop their arrow?
public class MyDataTracker {
private final Map<UUID, PlayerTrackingData> dataMap = new HashMap<>();
public PlayerTrackingData getData(UUID playerId) {
return this.dataMap.computeIfAbsent(playerId, PlayerTrackingData::new); // get or run the function, insert and return its value
}
public void invalidateData(UUID playerId) {
this.dataMap.remove(playerId);
}
}
Is an example
It could be further improved by checking arguments and making sure the player is online type before creating objects
If you right click while its flying its stops, if you log off it stops, if the arrow hits the player who send it it stops
ok
in that case in your DataHolder create two methods. startArrow and stopArrow
for now, just empty methods with no arguments
}
public static void stopArrow() {
}```
yep
Not static though
you will call those from yoru listener when you need
Do you know what static does?
so it works everywhere, I made all my methods static but thats prob cause they methods I need to use over multiple projects in my Utils class
All i know is that if 1 thing is static everything needs to be static or it wont work
nope
I'll read one later idk which one
let me guess, if I abuse static everything will be super easy at the beginning but after I made tons of projects and I have a lot of code I will regret it
static will break most things
Basically static and objects are like water and oil
They don't mix
Static basically means "this doesn't belong to any object but rather the type itself"
It has it's uses, but they are very specific
its* ^
yep
alr
too lazy to edit 🙂
mf
going to leave it there to annoy 😛
ok boomer
btw do I need to make multiple start & stop arrow methods, and when I rightclick i first have an ability for an arrow to hover infront of me, then I cancel it (so it falls down) when I leftclick and find a target and calculate the velocity towards the target and the next and the next then back to me and then I cancel it again and also delete the arrow
or can I put everything that needs to be stopped in the same method
no
you can add a createArrow or activateArrow method
start/stop will be used to... (self explanatory)
yeah rn i have
private BukkitTask homingArrows;
private BukkitTask hoveringArrows;```
the flyingArrow is the entity that spawns, the homingArrows is the calculation to the next target, and the hoveringArrows is the arrow hovering infront of me which needs to be stopped before I use homingarrows
I should add simular things in the start and stop right
no
or I mean the entity being created in the createArrow, and the other 2 in activateHovering and activateHoming
i don't have it yet, but I the bukkittask hoveringarrows (which is activated after summoning the arrow entity) makes the arrow hover infront of me (which is cancelled before I activate homingarrows) and when I activate homingarrows the calculation is made towards the targets & back to me
ah ok
I was going to do the homing part in start
basically in start you begin your Homing
in create you start your hovering
so you do need two tasks as Fields
no s on the end, as these are single arrows
homingArrow hoveringArrow
There are many optimizations you can do later, but for now a task for each is fine
Later is when you start thinking about animation sequences
//start hovering
//start homing after hovering stopped
}
public void stopArrow() {
//stop hovering
//stop homing later
}
}```
createArrow should start hovering. No tasks shoudl be running when you call create
Do I wanna put the code of the arrow hovering in that method?
//start hovering
}
public void stopArrow() {
//stop hovering
}
public void startArrow() {
//start homing
//no need to stop homing as it automatically stops when targets arraylist is empty
}
}```
alright
I also want to make a method to spawn the arrow in the air right, cause when I cancel the hovering I don't wanna completely delete the arrow with it
Not sure what you mean
when you call createArrow you shoudl spawn the Arrow entity where it needs to be and start a hover task
I copypasted everything to create the arrow from summining it to adding the damage value to making it start hovering into createArrow and commented it in my original code and typed DataHolder.createArrow;
half the code is red now tho so I should probably figure out how to link all objects
SHouldn't I just do this again but in the dataholder class
private Arrow flyingYakaArrow;
private BukkitTask homingArrows;
private BukkitTask hoveringArrows;
private double angle = 0.0;
private boolean movingLeft = true;
private Player player;``` cause it doesn't fix it
Why shall one not store a player. What changes
The Player object does not persist through logins
public void createArrow() {
Player player = Bukkit.getPlayer(UUID);
Best practice to reference by UUID
Does it stay same for sessions
yes
Can I send screenshots when I'm verified or nah
yes
ok imam create an account rq cause its annoying i can't send ss
You mean bings
how large are your balls
Date me first
create a thread
Hello is it possible to make a glowing entity not visible through blocks ?
how to find out the name of the plugin in order to add it to depend?
how can i get the hitted player with the ProjectileHitEvent?
It's probably the name defined in the plugin.yml
check plugin.yml or /plugins
#getHitEntity
And then cast to Player(but first check if it is a Player!!!)
"Does not working" is a useless statement. Please describe what exactly is not working, what you expect it to do, and what actually happens. If you get any console errors, also ?paste the entire stacktrace.
you can use runCatching to clean up the exception stuff
I will get rid of this whole mess completely, but first I wanna make this work at all
no error i want to remove after 10 seconds the victim from the nobw list
why did you reverse the mini message class name xD
also finally gonna start on the storage module today after I finish switching PineappleChat to gradle.kts
otherwise it gets relocated
to make shadowJar not touch it
because I'm relocating the shaded adventure and minimessage
I'll later create a separate module that's excluded from shadowJar but the issue is obv that I cannot pass an instance of the relocated Component into the actual paper event
so I have to serialize it w/ shaded minimessage and deserialize it with paper minimessage
why wouldn't you want it to be relocated? oh for paper minimessage
yeah because PlayerQuitEvent.quitMessage doesn't take a com.github.spigotbasics...Component 😄
idk I'm using minimessage for all messages anyway
once BungeeChat gets merged we can probably just do MM -> Json -> Bungee
everyone knows the real chads do PineappleChat -> Bungee though
Isn't gson serializer part of spigot
adventures bungee platform already does adv to bungee no ?
Are you passing the instance?
You can access fields and methods, but you have to pass the instance from which you want to get the member
Otherwise it just assumes static
the class is package-private
wtf I thought adventure dropped the bungee serializer
+1 ^
yes
maybe the instance is null, let's check
Apparently they didn't
sure
why my Bukkit.getScheduler not working?
i want after 10 seconds from the damage of the EGG on the victim the victim will get removed from the list nobw (List of UUIDs)
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof org.bukkit.entity.Egg) {
org.bukkit.entity.Egg egg = (org.bukkit.entity.Egg) event.getDamager();
ProjectileSource shooter = egg.getShooter();
if (shooter instanceof Player && event.getEntity() instanceof Player) {
Player attacker = (Player) shooter;
Player victim = (Player) event.getEntity();
// Add the victim to the list of hit players
im.setnobw(victim);
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
if(im.NoBowBoost.contains(victim.getUniqueId())) {
victim.sendMessage("E' gia' sotto effetto di un uovo!");
return;
}
im.removenobw(victim);
}
}, 10 * 20);
Bukkit.broadcastMessage(attacker.getName() + " hit " + victim.getName() + " with an egg! They are now on the hit list.");
}
}
}```
does anyone know how to test on a different java version
in gradle
im writing my library at java 8 but i want string blocks for testing so ive tried doing
tasks.getByName("compileTestJava") {
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
}
change tool chains
yk how?
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
np
Anyone know why I can't get the method through reflection?
Stacktrace: https://paste.md-5.net/ohibuhanec.pl
Full class: https://paste.md-5.net/vazocimehi.cpp
do paper relocate it
well it doesnt throw errors for getting the instance or class
prob
why do u have reversed class names
im guessing to avoid relocation
AST?
yh
technically there is a deserialize(String), but that's going to be in the implementation, as it's a generic <R> deserialize(R)
and it'll be a String
ItemStack adapter anywhere?
im using a config serializable that i got somewhere but doesnt seem to work well
im in 1.20.1 and it started to need logger and atomic reference adapter???
okay Gradle Kotlin is way better than gradle groovy wtf
How much extra storage does https://www.spigotmc.org/threads/custom-block-data-persistentdatacontainer-for-blocks.512422/ take up? I want to make something where every placed block has a UUID of the person who placed it attached to it.
@eternal night you were right about groovy 😨 I switched PineappleChat over to kotlin holy fuck
side by side be like random magic with shitty syntax highlighting and clear as day what's going on
How do I include my transistive dependencies in my final published jar? or should just publishing the java component work
^ nvm

I'm now gradle.kts pilled
Good decision 
also how fast is it, is it safe to check for it on every block break?
I have a Vector direction and I want to make a block display have that rotation, however since I need interpolation I need to use quaternions, does anyone know how I could go Vector -> Quaternionf
Is there a way to make the screen shake
as in frozen?
No I remember there is a function or something to make the camera tilt left or right as if the player is getting hurt
I found it player.sendHurtAnimation
If anybody needs it
yup, all good
i do that myself too to check if a block was placed or not
ok nice
its fast enough to not appear on any timings
one question, do you have coreprotect on your server
yeah
because an issue is that if a build was to get rolled back the blockdata wouldnt stay
probably not
also does it keep items when the block is broken, or do I have to remove the value myself?
remove yourself afaik
What is PineappleChat? LOL
like MineDown or MiniMessage
