#paper-dev
2787 messages Β· Page 3 of 3 (latest)
yeah i'll leave it for now i guess
tbf it does build quickly since i have a small plugin
probably takes like 2-3 seconds
so probably dont need it
And finally, the code cleanup stuff is from linter suggestions, like sometimes the IDE has suggestions what you can change
ahhh
i see
I would keep auto build disabled
You can see all the suggestions like that if you do Code->Inspect Code
There are a bunch of those you can turn on and configure too, beyond the defaults
Clearly my project is awfully buggy 
o
When I was learning Java (not as my first language) the inspections in there were helpful for pointing out some footguns
I don't think I have ever used that window, but I agree that it can be useful when starting out
But like when you have a file open, it will tell you at the top anyways
I turned a bunch of them on and read up on them to learn why it was potentially worth a warning
That just means that the files are not added to git
Yes
If you do git add ., they will turn green
And when you commit, they will turn back white
Modified files show up blue
imo they should show it like vscode beside the named with a letter what the status is
i thought for a second EVERY file had an error π
hmm
vscode uses colors too it just also has a letter
Modified files are yellow and have an M
yeah i like this better
is there an extension in intellij that maybe brings it back?
bring back what exactly?
vscode-like git tracking
like this
Is that one single letter really that big a deal though?
I don't even think it changes a lot
at a glance when you see the U you instantly know it's untracked
though since you're probably familiar with intelliJ's system that much it doesn't look like a big deal
Anyways it doesn't seem like there's a plugin for it
awh
Well, with IJ you can see it with the color!
true
Red file name always means untracked. If the file has an error, it will have a red swirly underline instead
yeah, you get used to the IJ colors pretty quick honestly. it's not better or worse, just different
and that red underline for errors definitely saves lives lol
Looks like a lot of these plugins already exist... I'll just release the source code and not publish it to modrinth i guess
i see
source code only is fine though.
sometimes people just wanna mess with it themselves
true but it'd be less likely for someone to stumble against my source code
But you never know
yeah true, weird people are everywhere lol
It's a project for you to learn, don't put pressure on yourself
Barely any of my own projects even make it to the surface of my GitHub
That's my fault for sure, but it's not a big deal
classic mistake lol.
good luck
always weird to look back at old code
Sure, but I just never put in the effort to properly create and maintain a proper public project
I have one single library that I maintain actively
i've been there
uh should I commit gradle-wrapper.properties?
yeah definitely commit it.
keeps the gradle version consistent for everyone
oh okay
You can even commit the wrapper jar.
i dont know if that's sarcasm
You can, i usually do since itβs free space and uhh too lazy to redownload it on other machines
nah he's right, you can commit it
oh
not purely required but fine to do
Good practice imo. Means people can just clone your repository without worrying about installing Gradle, or having the correct Gradle version
yeah Malfrador right, that's exactly why people usually commit it
You're supposed to commit the wrapper jar and the properties, that's what bootstraps gradle for the project
Oh sorry, No I ment it literally :D
gotcha thank you everyone!
exactly, just commit it and forget about it.
saves everyone the headache
no problem, glad we could help out
good luck with the plugin
thanks
anytime man
Should networking be async?
I send a networking request every hour, async scheduler or normal one?
As much as possible IO should always be async
definitely go async for networking.
Well, IO that happens while the server is running
normal scheduler will just block the server thread for a bit, not what you want
Reading a file in onEnable? Whatever, no one is playing right now anyway
Oh okay thanks
yeah but its still a bad habit to get into tbh.
Just a quick java thing, this should be volatile?
private static double something;
It's updated every hour in the network request
better off just doing it right from the start
yeah definitely use volatile if you update it in a network request thread and read it somewhere else.
You can't exactly run without a config file though
Thanks
otherwise other threads might not see the change
Like you might be able to load and parse it async if you have a reload later but for that first start you need it so you either load it on the main thread or spin up a thread and then just block the main thread waiting for it to finish
Yeah I asked because AtomicDouble also exists
So I thought of which one to use
yeah AtomicDouble works too, just depends on what you are doing with it
sometimes simple volatile is enough
If you have a single writer I believe volatile is enough, so long as it's just a single value
If you have multiple writers you need at least atomic compare-and-swap, if you have multiple values you probably just need an actual lock
yeah if you have more than one thread trying to change it, compare-and-swap is probably key
keeps things from blowing up, usually
volatile is still enough even with multiple writers, no?
the issue is if you try to do a divisible operation
i.e. n++
Yeah, the writer is just the async task
This Java tutorial describes exceptions, basic input/output, concurrency, regular expressions, and the platform environment
nah, multiple writers definitely mess things up.
if it's an indivisible op it shouldn't
you need atomically operations like compare-and-swap or synchronized
If you don't care which value wins and they have no relation to each other then sure, you can still do volatile
I can keep the endpoint link in the plugin itself right? It's an opensource no Api-key service. So I don't think that it hurts
atomic is another word for indivisible
x = 5 on a volatile member would be "atomic"
yeah that's fine.
since there's no key and it's open, not much to leak
yeah, simple assignment like x = 5 is atomic in java for volatile variables, except for long and double, those aren't guaranteed unless also volatile
How can I remove a certain amount of an item, from an existing stack which can have a different amount?
If player has 64 diamonds, the following doesnt remove 5 from the 64
player.getInventory().remove(new ItemStack(Material.DIAMOND, 5));
yeah that remove method tries to match the exact stack context, including amount.
you should set the amount on the item in hand or a specific slot instead.
Iirc removeItem does?
Oh or removeItemAnySlot
nah, removeItem removes the entire stack that matches the item type exactly, ignores amount too if I remember correctly.
Not from my memory
Void's issue is he just wants to subtract from an existing stack
Yeah, which is from my memory exactly what that function will do
I guess you have to implement the removing yourself, it's not a ready method to remove exactly 5 diamonds
I will try, one moment
yeah pretty sure that's it too.
Void should just modify the stack size directly and be done with it.
removeItem should work, removeItemAnySlot for player inventories though
https://jd.papermc.io/paper/26.1.2/org/bukkit/inventory/Inventory.html#removeItem(org.bukkit.inventory.ItemStack...) you pass it an itemstack of 5 diamonds and that's what it'll remove
nah Jan, I still think that might clear the whole stack if it matches the item type exactly. at least last time I checked that's what happened
Or it'll return an itemstack of 3 diamonds if the player only had 2 of them
You did it wrong then
See, i remembered correctly
modify the itemstack itself is safer
No?
If you already have the relevant slot then sure, just modify it
yeah that's what I was telling him
just modify the existing stack
If you're just trying to remove items from a player for a shop you probably need removeItem though
If you're trying to remove the items from their hand then you already know what slot to check and modify
removeItem works as suggested by @onyx portal,
it removes the given amount from a stack that has enough, OR if there are enough across the inventory (e.g spread out)
thank you very much π
Make sure you don't ignore the return value
yeah that's true
Empty hahsmap = success, anything else = not success
always gotta check if it actually removed everything you wanted
If it's not empty you need to give them their items back and cancel (or do a partial action if that's a thing you can do)
good idea, thank you
oh, so it will remove some if it can π€ oof
not the place
wrong channel bud
Oh wich Channel is the Right
not in this server, but you can ask in helpchat from #community-guilds
This is currently the GUI where all our server replays are listed, but I find it a bit cluttered and also pretty boring. Do you have any ideas on how we could improve it? Feel free to suggest something out of the ordinary, I like to experiment, so it doesn't even have to be a GUI...
Fair, what type do you recommend? Never had things listed in a Dialog. just some basic settings
maybe try something like a physical map in-game with markers
or just make the chat feel like a replay list with hover effects
kinda out of the box but could be neat
you still want to use volatile even for word-sized fields
instruction reordering moment
I think just using lists in standard inventory GUIs usually works best.
keeping it clear and simple unless you really wanna try to push the visual side
Inventory GUIs as a list are nightmares because you have to hover over everything to figure out wtf it is. Dialogs let you use text. Whether for buttons or just for a big body with clickable text, it's much easier to communicate info to the user.
yeah but standard inventory lists are simpler to code and players are used to them
dialogs can feel kinda weird if you just list tons of stuff
x = 5 is atomic [β¦] for volatile variables, except for long and double, [β¦] unless also volatile
π€
Don't let "people got used to garbage" get in the way of progress!
https://github.com/mfnalex/CustomBlockData
am i doing something wrng
I mean, doesn't look like it extends persistent data type but that's also not our library
okay
hey everyone, what is the easiest way of preventing players from changing their helmet?
i already use the inventoryclickevent and it works fine but when the player right clicks the air with a helmet it still changes.
what event would be best to cancel for that?
this is for a minigame so it doesnt need to be pretty
try canceling PlayerInteractEvent when they right click with the armor in hand
ah yeah, makes sense, ty
when im kicking a player from my mc server in the backend code, it shows the velocity You were kick from ... and then my message, can i somehow override that?
Maybe with a velocity plugin?
yeah, use PlayerKickEvent for that.
Or maybe it has some config option, I dunno
you can change the reason there easily
They are changing the reason, velocity is wrapping that reason with an extra message
That would be a #velocity-help or #velocity-dev thing I guess
yeah velocity loves to add its own formatting.
so i have to perform my kick on velocity?
you might have to dig into its configs or like Amaranth said, check for a velocity plugin to force it.
thank you guys, i guess im gonna put that code on the proxy
yeah that's probably your best bet if you want full control over the message
yeah
bet
You don't need to move all the logic over, assuming you just always want to kick them when a server kicks them and always want to only show the server's kick message
You can make a simple velocity plugin that listens to https://jd.papermc.io/velocity/3.5.0/com/velocitypowered/api/event/player/KickedFromServerEvent.html and does something like event.setResult(KickedFromServerEvent.DisconnectPlayer.create(event.getServerKickReason().orElse(Component.text("Disconnected"))));
I think, I've never used velocity before so this is just from reading javadocs
yeah that seems like it would work to just pass the server's reason through
wouldnt that just always be disconnected?
ohh
i see
nah it's data on the block, check BlockData for farmland
yeah i realized thanks
What is the recommended way of accessing config.yml data from another class?
I have an entry class which extends JavaPlugin and loads the config when onEnable is called.
Then I have a separate class which contains logic for a /command - what is the recommended way for this case?
Any standard java technique. Pass the reference to the main plugin class into the command is a fine strategy. Then you can plugin.getConfig or whatever.
just pass your main class instance to the command class constructor.
classic dependency injection works fine.
Also maybe don't have AI build your questions so formally. π
tru, formatting made it look like a legal document lol
My brother in humanity, I can write with correct grammar. Dont need Ai for that
Alright, thank you
I think it was more about the markdown not grammar
You wrote with ## headings and all, which we tend to only see when someone does not speak English and asks AI to reformat without too much clarity on how to format π
yeah that headings markdown is kinda unusual to do by hand
but it made the point clear at least lol
It's all good, I wasn't assuming malice.
how do i create a fake display entity? is there docs i can read to
using nms or packets also you can just hide it by default
You're right, its quite formal how I present it Xd
by default?
check protocol packet events for fake entities
or protocollib makes it way easier usually
i mean you can spawn a simple display entity, then set it to be hidden by default then just show to whoever you need
oh okay
if not just use packet events + EntityLib or nms
i more wanted the like removal aspect
wym by removal aspect
just send a destroy packet for that entity to the players who shouldn't see it
or you can just use Player#hideEntity, or alternatively Entity#setVisibleByDefault + Player#showEntity
yeah thats what i said
Why manually send destroy packets when you can use the proper hiding setup? Otherwise the clients will still get info about entities as they change.
display entities are not expensive you dont need them to be packet based
Lancelot had a very different proposal, which is what Emily's replying to
yeah that's pretty much what system32 was saying. using packet approach or the api, just depends on what you prefer
true displaying entities is kinda fine but hiding them properly with api is less messy for sure
Combining creating real entities and hiding with packets makes for a nasty mess, and is what the whole hiding API exists to solve.
i think that lancelot just said that if he wanted to do the packet way
i want the entity to like disappear if the player isnt close to it so i was worried that tracking the entity would be difficult since fake entities time out
yeah but mixing both is asking for trouble tbh
but i realized you can probably just save the entity to the player anyway
Entity.isPersistent exist on the api
just use the api
that destroys the entity if the chunk was unloaded
hm okay ill experiment thanks
gl with experimenting, let us know how it goes
π«Ά
spawn your think, hide by default, show when needed, leave persistent property do his things when chunk unloaded, then respawn it on ChunkLoadEvent or PlayerChunkLoadEvent when needed
yeah using the api is simpler most of the time. just gotta manage the events
Can I make a bossbar with no bar? Like just the text
youd need a texture pack
yeah empty texture for the segment is valid. or could probably mess with client sided bossbar packets if you really want to avoid it but that's overkill
what�
just formatting weirdness from earlier lol, don't worry about it
What happened
Ban reason covers it. Also this ain't the channel for ban stories π
Ah
can i set gamerules in code, for the whole server?
World.setGameRule()
i guess you can use WorldLoadEvent for that or onEnable method using postWorld
OOF π
Is it a good or bad practice to not replace a config file ?
saveResource("config.yml", false);
Well, what are you trying to do? Overwrite the user's changes?
For example, if there is a plugin update with new fields in the config file, how should it be handled by the admin of server π€
or is it better to just use defaults if the new settings dont exist in the local file
how should it be handled by the admin of server π€
by reading the changelog before updating plugins π you can probably do some sort of config migration if you really want to, adding new entries, deleting removed ones and keeping the user's ones
or yeah just run defaults for missing settings, that's the simplest option, but you ought to document config changes on updates
configurate >
umm hi, could someone pls explain how I can get the attack cooldown at the moment of hitting an entity?
i use to do this by getting Player.getAttackCooldown() during an EntityDamageEvent, but now the cooldown resets before the event is fired D:
try PrePlayerAttackEntityEvent
you should save the new file, then copy the users data from the old file to the new one
then delete the old one
no way they rly added the
truly a paper moment, ty tho
How long does it typically take for paper prβs to get reviewed?
5 seconds to 2.72 years
alright
how I can teleport player into custom dimension
you can get the dimension with Bukkit.getWorld(Key.key("yourns:yourdim")) and then you can do Player#teleportAsync(new Location(theworld, 0, 200, 0));
you can
ok
Bukkit.createWorld(new WorldCreator(new NamespacedKey("ns", "key"))
.environment(World.Environment.NORMAL)
.seed(1234));
@azure karma
this will either create or load if it exists
and it will return the World instance
I am fairly new to the plugin development game. I developed a mob stand that kills adults and leaves babies along. Not quite done yet but stress test is here. What would be acceptible time considering it is 1) Scanning for all mobs and getting the ones that are slated for slaughter (babies and adults are set seperately on the stand config so user can decide wether to kill babies or leave them for each animal type, same for adults. then dealing damage to cause them to die and letting game mechanics determine drops.
ok
100ms seems massive
What exactly are you doing? And hopefully not on the main thread?
No. This thing is killing those mobs.
scans every so often and kills qualifying mobs. I have a string of command blocks set up on repeat to summon mobs and this scans every few seconds.
seems rather slow to me
though I guess calculating drops for 2k entities might take a bit.
Best to use spark with --only-ticks-over 50 or so to see what exactly is slow there. if its your plugin, or the loot stuff
This isn't calculating drops. It is dealing each mob damage and letting the game sort it.
yes, and the game will calculate drops
2,300 mobs in that screenshot alone.
if its not that I can't imagine 2k mobs taking 100ms
getting nearby entities is very fast. removing them should be too
only entities.
you just do getNerbyEntites?
[02:45:33 WARN]: [RS-MobStand] Slow cycle: 50.60ms | Killed: 266 | world -8 -60 -9
or World#getEntities
armorStand.getNearbyEntities(
radius,
radius,
radius
)
Can you send a spark report? Something seems really off
Not sure how to do that.lmao
^
ive never used spark
Spark is a profiler, you can install it as a plugin, then you just start with that additional param, let your plugin do stuff and then stop and send us the link
ok gimme sec.
(it also comes with Paper directly, no need to install it manually)
/spark profiler start --only-ticks-over 50, then run your kill stuff, then do /spark profiler stop and send the link here
Just did the same with my custom mob plugin, killing 5k entities in a radius takes 16ms. So something is off there for sure
How?
The 1.21 Update
Stable Paper and Velocity 1.21 builds have been released! As always, backups are absolutely mandatory. After upgrading your world to 1.21, you cannot downgrade back to a lower version!
We would like to thank everyone that worked on this update:
4drian3d and Gerrygames for their...
[02:45:13] [Server thread/WARN]: [RS-MobStand] Slow cycle: 102.86ms | Killed: 1564 | world -8 -60 -9
[02:45:33] [Server thread/WARN]: [RS-MobStand] Slow cycle: 50.60ms | Killed: 266 | world -8 -60 -9
[02:45:43] [Server thread/WARN]: [RS-MobStand] Slow cycle: 59.95ms | Killed: 806 | world -8 -60 -9
[02:48:19] [Server thread/WARN]: [RS-MobStand] Slow cycle: 85.24ms | Killed: 2323 | world -8 -60 -9
[02:53:09] [Server thread/WARN]: [RS-MobStand] Slow cycle: 46.94ms | Killed: 997 | world -8 -58 -10
[02:53:19] [Server thread/WARN]: [RS-MobStand] Slow cycle: 44.61ms | Killed: 1092 | world -8 -58 -10
[02:54:48] [Server thread/WARN]: [RS-MobStand] Slow cycle: 36.31ms | Killed: 1134 | world -8 -58 -10
[02:54:58] [Server thread/WARN]: [RS-MobStand] Slow cycle: 7.45ms | Killed: 137 | world -8 -58 -10
[02:55:08] [Server thread/WARN]: [RS-MobStand] Slow cycle: 5.29ms | Killed: 75 | world -8 -58 -10
[02:55:18] [Server thread/WARN]: [RS-MobStand] Slow cycle: 25.24ms | Killed: 362 | world -8 -58 -10
[02:57:07] [Server thread/WARN]: [RS-MobStand] Slow cycle: 40.33ms | Killed: 751 | world -8 -58 -10
send the link
that really seems more like the server is struggling with the entities themselves than your killing logic being the issue
how are you measuring those "slow cycles"? because if that just tick time, its somewhat meaningless.
But otherwise that looks like expected performance with 1k entities on 13 year old mid-tier CPU
Measures execution time of the scan/kill cycle.
Scan entities, check against stands filters, deal damage is need and move to next.
And yeah, the game was laggy as all get out when it cycled. I have it waiting a long time in between kills so I can stress test it.
actually it was lagy BEFORE it cycled. it just cleaned it up and sped it back up.
But generally spark shows what I suspected. you can expand the individual entries of the profiler (starting at your SlaughterTask) to see what exactly is taking how long.
And what takes the most time is indeed creating the items for the dropped loot
If you want to fix that the best way is probably precalculating the loot. e.g. loot for mob type X times amount of mob. And then just removing the entities instead of vanilla damaging them, and handling the loot separately in your plugin
Ok. Thanks. backto the drawing board. lmao. This thing so far has totally pushed the limits of what I know. lmao
where should I define my command trees and register them? in a new class or? I am new to java and plugin development
that's basically up to you. general rule of thumb is to not have classes that are longer than a couple hundred lines
(of course the structure should be logical, but large classes are often an indicator for a messy design
Alright thanks mr webhook
is EventPriority.LOWEST the first or last to get called
first
the priority for events is from the perspective of who should have the last say on the result, so lowest goes first, highest and then monitor go last
okay
might be a stupid question but can those classes go into a seperate commands folder or just in the same directory as the main class? And in what way should i connect the other classes like commands to the main class?
they can go wherever you want
of course you need to invoke their code somehow from your plugin's entrypoints in the main class (or from registered event listeners)
ummm, it is world, not dimension
in this context World = dimension
this will create a new entry in dimension subfolder
in relevant ns folder
what version are you on?
1.21.11
ah
I am talking about 26.1
I would say dimensions are not supported this way pre 26.1
uhhh
Mojang fixed up their world storage, paper followed
pre 26.x will use the older craftbukkit layout of the files being in the world container folder (the working directory by default)
You should backup your worlds
before the migration
This is due to vanilla changing the world format in 26.1
And then run the server again and let it migrate
It is necessary
oh so I don't have to do anything, but just back it up? thanks π
Is there a way to distinguish (or maybe is there another event called for that) whether PlayerDropItemEvent was dropped from hand or while viewing inventory?
how can you add a material argument with argument()
you could check if the player currently has an inventory open when the drop event is fired
and how do you check if the argument given is then placeable
I should've explained what I wanted to do first, sorry. I'm trying to prevent changing amount of certain item stacks by players. I already implemented that by doing checks in InventoryClickEvent listener, but now I want to prevent one-item drops outside inventory. How could I do that?
I want to allow the one-item drop if the quantity is 1
Would be checking whether the player has an inventory open and assuming the drop is a hand drop if the inventory is closed a good idea?
Inventoryclickevent is the way to go, you can check clicked item or cursor item
Depends if it is q drop or click outside
Use the registry argument type with RegistryKey.BLOCK, example for ITEM https://docs.papermc.io/paper/dev/command-api/arguments/registry/
Yes, I've already handled InventoryClickEvent, but now I want to prevent one-item hand (outside inventory) drops if the item in inventory has quantity other than 1
why not just cancel the event for the condition you specified at the end? (quantity > 1)
If quantity is 1 and that is a quantity of the stack in inventory, I want to allow that
yes, but that event is also called for inventory clicks, I cancel one-item inventory drops, but I allow full stack drops, which would also call the event you specified
Outside of basically tracking if a click event was fired, there probably isn't a way to do what you're asking
lack of a cause stack means that there is often 0 real context of what triggered an event as a side-effect, and the client is basically always considered to have the player inventory open
i can delete dimension file in runtime?
Deleting a folder using File.delete() doesn't work.
Adding drop reasons to the event or creating a new event for that wouldn't be too hard, no? At packet level it's easy to distinguish that. Would such a change be even welcome to Paper? If so, I might be interested in doing that, but later. It's not that important for me for now.
You need to unload the dimension first, then you can do it though this is quite unsupported use case, but it is working for me
What about the Material type?
The context of why an item was dropped doesn't exist there, it's just a general method with a bunch of params called from a bunch of places
Material is not a valid mojang thing, that's a bukkit holdover
yeah, but we could add an additional parameter, adding an unknown drop reason to maintain compatibility with plugins calling plain NMS methods for some reason, or just make a new event
The problem is generally how invasive in getting the context to the event is
not "is it technically possible"
what are these about? im on paper
I think that is how many other events with reasons work as well
Yea, but those events usually have a shallow enough context surface that it's not a design nightmare or have so much utility that said nightmare is worth it
the folia schedulers have existed on paper for a while now
that used to be the biggest API difference between those platforms so its a sensible port, although obviously the same call doesn't do the exact same thing on folia and paper
yeah but the block.settype function requires a material and so does the ItemStack class
There is a method to convert to a Material somewhere iirc
otherwise the name should generally match across the XType to the Material enum
just a "The Type things aren't really first class yet"
hypothetically could paper ever have custom blocks that the minecraft client sees as an existing block? for example could there be a "Super Stone" that drops an item with meta data but the client sees it as regular stone block?
im 99% sure this has to do with the fact that the command trees are not sent the same in the DECLARE_COMMANDS packet between the two versions. i am not sure if this has to do with the patch (the PR you mentioned) the Machine Maker authored
if someone from the Paper team can shed some more light on this that would be great
if the intent of the PR was to always force the client to ask the server for completions, then that clearly doesn't seem to be the case.
also- its worth noting that i am able to get the intended suggestions by modifying the DECLARE_COMMANDS packet before it reaches the client.
that should be possible already, you'd just have to do the job of carrying over that special metadata between the item/item entity/block
people usually do that via PDC + listening to specific events
man i wish mojang would just allow for custom blocks with their datapacks. it would be so nice to have that on paper
you got it the other way around, the intent of the PR was to remove the patch making the client ask the server for completions (for entity arguments). I imagine the patch was removed because it ended up causing more troubles than it was worth. It is what causes the difference between the declare commands packet
oh so you're saying the patch was reverted in this commit. i understnad
yeah, so the behavior you saw before was due to a Paper change, not necessarily how it works
whether that was intended or not is something probably worth making an issue. I imagine there's more to just modifying the declare commands packet that we're not seeing here, like the duplicated names in the tp command
though not sure if it is gonna get much attention since they removed the patch because Paper doesn't want to deal with it lol
its in the works
right now theyβre doing that for items
and blocks are next
seriously? where have you heard that from?
theyβre slowly (or even fast) making everything data driven
just look at the code and the update changelogs
you can see how many changes theyβre doing to make things data driven
No soliciting here
<@&748618676189528155>
ive been keeping a close eye on the new logs. i really hope they release custom blocks soon, it would be so fun to make plugins with them
i just have a habit atp of pinging mods cuz almost every day there are some people soliciting and not listening when people tell them not to
It will take a couple of drops before they do that i assume
They have been working on items since 1.20.5 iirc
yeah ive been really enjoying the item changes
oh and also theyβre now focusing mostly on VV so the development of data driven features has been subsided
Is PlayerTradeEvent called when a trade is completed through a custom merchant inventory?
Try it and see, but it should indeed call it if the inventory is made with menu api
Id say thats probably an impossibility ngl do you know when this event is triggered?
Do you have a villager? Or a bukkit created merchant
Bukkit created merchant for a custom trader system.
You want to be using PlayerPurchaseEvent
Is that the same event but for custom merchant menus?
Yes
Thank you, Miles.
if (this.merchant instanceof AbstractVillager abstractVillager) {
event = new PlayerTradeEvent(...);
} else if (this.merchant instanceof CraftMerchantCustom.MinecraftMerchant minecraftMerchant) {
event = new PlayerPurchaseEvent(...);
}```
honestly this difference kinda sucks and makes pretty little sense, but hey we ball
Yea I donβt see why itβs two separate events for the same things.
probably some historic thing hopefully rather than an actual concious choice
From what I see trade event doesn't have its own handler list, so listening to purchase will give you both events
The difference is that trade event also gives you the villager mob, that doesn't exist for custom merchants
oh yeah there you go ^
But you could just do a null check for that and have it in one event. Oh well I guess it doesnβt really matter.
The event was added 5 years ago when the logic between merchants and villagers was more seperate
[Amendment: Alexander protonull@protonmail.com]
PlayerTradeEvent is used for player purchases from villagers and wandering
traders, but not custom merchants created via Bukkit.createMerchant(). During
discussions in Discord it was decided that it'd be better to add a new event
that PlayerTradeEvent inherits from than change getVillager()'s annotation to
@Nullable, especially since that'd also infringe on the implication of the
event being about villager trades.
making a method return nullable is a breaking API change
Hello guys is there an alternative to ChatColor.Bold I'm aware ChatColor is now deprecated so I'm just curious if there's an alternative to it
In MiniMessage it's <bold>
Or text decoration when making the component
Is there any way to reliably disable sprinting/crouching?
is there a way I can detect a held right click on like a skull item or like a wither skull? looking through java docs and i'm lowkey stuck
Thank you !
Nope, you can approximate but most often it's not good enough
@unborn mist
My plugin doesn't have a traditional event handler, because it handles different players differently, it uses protocollib and hooks into SYSTEM_CHAT, DISGUISED_CHAT and CHAT packets.
This makes it even worse for interference because it's guaranteed to run after ANY event handler, on the flip side it's more consistent and I know my message won't be modified afterwards.
Sprinting would be kinda possible, not hardly crouching. Maybe more context would be helpful and in your usecase there could be something useful
Is there an API way to get the owner of an ender chest? I see PlayerEnderChestContainer.getOwner, but there doesn't seem to be a way to access it.
if it is guaranteed to run after event handlers, then you cant do anything about it except remove the plugins messing with the data
or add an event handler on AsyncChatEvent, regex the minimessage, and add it back... but that's hacky.
Dang I'm trying to make like right click thing and I can't even get a shift right click found in the java docs or atleast proper found
yeahhh it's advancedchat stripping messages
this really feels like one of your plugins sanitizing the string
already figured it out, AdvancedChat is :P
Never mind, I see the PR to make the holder the player
definitive fix:
give permissions advancedchat.chat.colors and advancedchat.chat.magic and it stops stripping minimessage tags.
was 100% not a paper sanitation check as I had initially suspected.
this behavior is documented nowhere...
which part of Canada you from
oh lol
Switzerland
Anyway other than clickevent is there any minimessage that would be dangerous to allow in player messages?
Anyone know ideas possibly on shift clicking skulls? Push me in the right direction on java docs?
Is there are more preferred way of defining and parsing vanilla minecraft enchantments?
[06:32:44 WARN]: [org.bukkit.craftbukkit.legacy.CraftLegacy] Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!
In config.yml file, enchantments are named like minecraft:protection
and in the code, it is parsed with:
Material material = Material.matchMaterial(materialKey, true);
? enchantments aren't materials?
oh π€£ youre right, im tired π©
ideally you'd use the registry
though your example leaves me confused as hell as to whether you actually meant enchantments or materials
Registry.MATERIAL.get(Key.key(materialKey))
ideally you'd use Registry.ITEM/BLOCK accordingly depending on what you're parsing though
Forget the material stuff, I was thinking wrong about it. What im trying to achieve is define enchantments inside the config.yml file and use them in code to get certain other related config
perhaps i was overthinking about "minecraft:" prefix, wondering if using the name directly would conflict with some other plugin. π€
you just get it from the enchantment registry
RegistryAccess.registryAccess().getRegistry(RegistryKey.ENCHANTMENT).get(Key.key("minecraft:sharpness"))
I see now, thank you π«‘
for what is worth, almost every enumerated thing in the game has a registry behind it
so how you obtain them ends up being the same all around
public void onPlayerMapFilled(PlayerMapFilledEvent event) {
Player player = event.getPlayer();
ItemStack item = event.getCreatedMap();
MapMeta mapMeta = (MapMeta) item.getItemMeta();
if (!mapMeta.hasMapView()) return;
MapView view = mapMeta.getMapView();
if (view == null) return;
view.setCenterX(0);
view.setCenterZ(-15);
view.setWorld(SUMMER_WORLD);
view.setScale(Scale.NORMAL);
mapMeta.setMapView(view);
mapMeta.displayName(MiniMessage.miniMessage().deserialize("Treasure Map"));
item.setItemMeta(mapMeta);
}```
Can anyone tell me why the item name isn't being changed? Everything else such as the map view is being changed properly.
In what event would a world lose its UUID and be given a new one? I'm trying to figure out if it's worth storing the world UUID AND world name in my database for a home location.
UUIDs are persistent.
I suppose someone could edit the file storing the uuid
So basically in no common/uncommon scenario would that happen?
World uuids are a bukkit thing, maybe loading the world in singleplayer then back on server could change its uuid
hmm
i always store just the world name, so server admin can switch worlds if they have to
I'll test that
World names are perfectly safe to go off as well, like teeth said. The only thing that can go wrong there is if someone changes the world name. But if you just leave the server running normally it should be fine.
Maybe I'm missinterpreting what you're saying, but wouldn't that make the homes useless?
How?
event.getCreatedMap returns a clone of the event's item, make sure to event.setCreatedMap after messing with it
Thank you. I will do that.
It sounds like he's talking about a completely different world
No. You can just use the world's name to save homes rather than UUID.
So in your file or database or whatever, you can store it as just "world" rather than the overworld's UUID.
Do exactly what you were doing before, but don't use UUID: just use the world folder's name.
I was doing both before (name as a backup), but I guess that'll work
You only need one, as long as you don't have two worlds with the same folder name (which should be impossible anyways) you're fine.
Is it possible to define custom map dimensions to make the map be exactly the size of the build you want it to be?
Looks like MapView.Scale is the best you get
Yea but I have to have a border around it with that.
There is MapRenderer
Is there any way to get a client's distortion effects value? Packets, NMS, etc are all ok for me.
no, those accessibility settings values are not sent to the server at all
is there a way to reload a certain plugin ?
bit awkward to stop/start server each time
you can setup hotswapping in your ide, given your server is started through the runServer task and not externally
π is there any guide for this
are you using intellij?
yes
Im not sure how to go about that π€ Currently what I do is build the project, take the jar, place inside plugins folder and restart server
why not use the runServer task instead?
Im not aware of such thing, where can I find a guide on that
LivingEntity#setNoDamageTicks(0); remove invincible time after damaged only one-time or permanently?
once
cool, thanks π
Hi, is it normal for TextDisplay entities to disappear on world change?
It does for me
What do you mean by world change? Maybe chunk unloading?
So basically, suppose there is a TextDisplay in the hub world. A player goes ingame and when the game ends, they get teleported back to the hub world, they are not able to see the displays after the world change.
Are the displays still there?
yes other players can see it
Show some code how you're spawning them
I am using FancyHolograms
However, displays summoned using /summon command don't show up either
Yeah those are packet based entities, it's a plugin issue
Are you sure you can see them before switching worlds? Maybe malformated data on spawn
Hm no I was wrong, displays which are summoned are indeed visible after changing worlds
Must be a plugin issue
Do I understand correctly, does the radius set using Explosive#setYield get doubled in actual calculations?
im trying to mimic fishing loot as if the player actually fished, but not 100% sure im doing it correctly:
ItemStack rod = player.getActiveItem();
if (rod.getType() != Material.FISHING_ROD) return;
AttributeInstance luckAttr = player.getAttribute(Attribute.LUCK);
double baseLuck = luckAttr != null ? luckAttr.getValue() : 0.0;
int rodLuckLevel = rod.getEnchantmentLevel(Enchantment.LUCK_OF_THE_SEA);
float totalLuck = (float) (baseLuck + rodLuckLevel);
LootContext context = new LootContext.Builder(player.getLocation())
.luck(totalLuck)
.build();
Collection<ItemStack> loot = LootTables.FISHING.getLootTable().populateLoot(ThreadLocalRandom.current(), context);
Am i interpreting how luck of the sea works correctly? the wiki doesn't really state how this modifies luck, only how it changes the drop chance for each category. Did i also create the context correctly? theres builder methods for Β΄lootedEntityΒ΄ and killer but i assumed it didnt apply for fishing
ah, looks like theres some unexposed params i need to set in the loot context, like the item used itself, ill just use nms in that case
If I want a screen shake effect (and also shake on third person), is it best to do this on a shader? Not sure if there's a pure plugin way to do it
You can do that with plugin
Huh, can you give me some pointers? Since naively moving the player's look dir is not getting me what I want
Oooh
This is seriously cool, how does it manipulate fov in there, though?
Since the coroutine seems to only be updating pitch and yaw
Regarding permissions, is it enough to have permissions declared in the plugin.yml file? or do I also have to perform a check within the code itself?
# ...
permissions:
kebab.abc:
default: true
description: Allows a player to eat kebab, yumyum.
commands:
kebab:
description: "something something..."
permission: kebab.abc
permission-message: "You dont have the required permission."
usage: "/kebab"
if you register the commands via the plugin.yml then it is enough
if you manually add them to the command map via the API then you need to set their permission in code
What's the best way to register permissions for a paper plugin?
rn I'm just awkwardly registering them in on enable, but it's kinda awkward bc if i register a perm that already exists it just throws an error >.<
why are you registering permissions 
i mean you can just shove your permissions in your paper-plugin.yml ?
if you're doing things dynamically, the api for registering permissions hasn't changed for over a decade
why is ChannelInitializeListenerHolder not in my classpath
i don't know, are you using paperweight.userdev to depend on server internals?
no
well, that's why
that class is an internal class, not exposed in the API
to access server internals you need to use the paperweight.userdev gradle plugin
will this make my plugin version specific if im only using ChannelInitializeListenerHolder?
I mean, you're accessing internals and while that is not around logic which changes often, it does not have the safety holds of the API when it comes to compat, etc
that class was not always present, and you are at the mercy of, netty APIs, minecraft changing the name of its pipeline handlers, etc
i mean as long as paper loads my plugin thats fine
while it isn't going to lock you to one version only and exclusively, it is something you need to take care of and read up potential changes when new versions are relased
Is it possible to disable totem use on death (I want to add a limit for max one totem use per minute)
you can cancel the EntityResurrectEvent
thx
Is there an know issue that PreFillProfileEvent and FillProfileEvent have no function?
yes
While Networking, I am sending a request, and the response contains ASCII letters. and when I use that response I always get question marks. I always specify the charset as UTF-8 but still doesn't work
I specify UTF-8 in the ContentType header, in the BodyPublishers of the request, and in the BodyHandlers of the response, nothing works
show the code
how are you displaying contents?
Just printing it out
Printing what sendMessage() returns
intellij idea terminal?
Yes?
well, i've got question marks too thinking it was my issue, however then i tried sending same message in minecraft and it worked
are you using gradle runServer by a chance
i suspect it's either gradle or intellij idea terminal just does not support non ascii charactors
I tried this networking in a normal Gradle app
To print the response and see how it looks like
try setting
org.gradle.jvmargs=-Dfile.encoding=UTF-8 in gralde properties
i havent tried this though
hmm you cannot set a Type of block using BlockType?
I have my IntelliJ set to UTF-8 File encoding
nope
gotta convert to Material
try anyway
gradle.properties
i meant
it is usually advised that you set the file encoding of the compile tasks
that just sets the encoding when you create a new file in intellij, the gradle property sets the encoding for the JVM running gradle which is different
tasks.withType<JavaCompile>().configureEach {
options.encoding = Charsets.UTF_8.name()
}
tasks.withType<ProcessResources>().configureEach {
filteringCharset = Charsets.UTF_8.name()
}
https://javadocs.packetevents.com/com/github/retrooper/packetevents/wrapper/play/server/WrapperPlayServerPlayerAbilities.html
paper didn't expose fov modifier
declaration: package: com.github.retrooper.packetevents.wrapper.play.server, class: WrapperPlayServerPlayerAbilities
okay that did not work unfortunately
and that is also different from the gradle JVM encoding, which is also different from the server jvm encoding
:):)
jvmArgs("-Xms1G", "-Xmx1G", "-XX:+AllowEnhancedClassRedefinition", "-Dfile.encoding=UTF-8")
minecraftVersion("1.21.11")
downloadPlugins {
github("MilkBowl", "Vault", "1.7.3", "Vault.jar")
// url("https://ci.dmulloy2.net/job/ProtocolLib/lastSuccessfulBuild/artifact/build/libs/ProtocolLib.jar")
hangar("PlaceholderAPI", "2.11.6")
github("GoldenShad0w", "DisplayEntityEditor", "v1.0.17", "DisplayEntityEditor-1.0.17.jar")
url("https://ci.minebench.de/job/FakeEconomy/lastSuccessfulBuild/artifact/target/FakeEconomy.jar")
url("https://download.luckperms.net/1631/bukkit/loader/LuckPerms-Bukkit-5.5.42.jar")
}
}
``` i'm crine this also doesnt work
which is also different to your terminal's encoding
and your shell
text is beautiful
intellij run terminal sucks
it doesn't display colors either, I just run the gradle tasks on a separate terminal now that IJ handles outside changes well enough
ok maybe not...
Block#setBlockData with BlockType.AIR.createBlockData() works... not sure why i think was a different thing...
i don't really use intellij for anything other than programming and managing the project's files
git and gradle i do wholly on my system terminal
same, except maybe for the merge conflict view, IJ's one is pretty nice
π’
i mean, i have no idea what you're printing
blame powershell Β―_(γ)_/Β―
This is not a PowerShell problem
Everything works fine for me.
well, i don't use powershell so i can't know
built in powershell doesn't support other charsets like utf 8 from what I remember, try installing latest powershell or use command line
paper-plugin.yml allows for permission definition? the docs did not hint at that, my bad
Well, the docs only mention differences to the normal plugin.yml, and there is no difference at that point.
ah, I see...
Since commands and permissions are mostly tight (tied?) together the assumption is understandable.
for some reason I thought that everything not mentioned in the guide just didn't exist. Since the only thing hinting that it only shows the differences is:
This will not act as a drop-in replacement for plugin.yml, as some things, as outlined in this guide, need to be declared differently.
tho I understood that as, you'll see the differences by reading the guide, not this guide shows the differences.
so I just thought, no commands mentioned? makes sense, since brigadier is the new norm.
no permissions mentioned? I guess I'll need to register them myself.
Your second part reads to me the same
Commands is a huge difference and really mentioned there.
well, it was more of a, this shows everything that is different vs a this shows everything, you'll see whats different yourself
I mean yeah, my bad, but I just thought, ah permissions are probably also no longer a thing in there. anyways, I guess they still exist there ^^
Stuff like that is generally going to be down to your windows config, there is an option to enable beta support for Unicode somewhere that will probably fix it
not using powershell core in the big 2026
Wdym powershell core
it comes installed with windows 11 nowadays, the old windows powershell has been long deprecated though still shipped with the system
the readme explains the difference
Hello yβall,
Am new to plugin development, but I do have a bucket goal in mind for down the road
I wanted to know how feasible it would be to detect when a village is being generated and then add an additional building (via an nbt structure file) to that village
it should be simple enough, you'd just have to use the AsyncStructureGenerateEvent to hook into village gen and then place your structure beside it. You can load structures using the StructureManager (gotten from Bukkit::getStructureManager)
can i make it default? or how do i make it so intellij uses that
if you already have it installed, you just have to go to IJ settings (Ctrl + Alt + S) -> Tools -> Terminal -> Application Settings and set the shell path to pwsh.exe instead of powershell.exe
well, I say simple but you're probably going to run into issues like how to position your structure properly without the carving out a mountain or things like that, for more detailed control you'd use a chunk generator but that makes things a whole lot more complex
you also have to make sure the chunks are loaded when you try to place the structure iirc
well that didnt fix utf-8 issue but thanks
i mean, utf-8 output works fine as far as i can tell, i think issue is in gradle
what code did you use to try it
try {
MiniMessageTranslationStore store = new LocalizationLoader(
new File(getDataFolder(), "locale"))
.loadStore(Key.key("cult:clans"));
GlobalTranslator.translator().addSource(store);
} catch (IOException | URISyntaxException e) {
SneakyThrow.sneaky(e);
}
getServer().getScheduler().runTaskTimer(this, () -> {
getServer().sendMessage(Component.translatable("clans.already_in_clan"));
}, 20L, 20L);
pardon formatting
your localization loader I assume is the one you shared earlier in #adventure-help?
yep
my pet peeve with it is that it is using the old File and JarFile APIs, even though they end up being more succinct which bothers me even more
do you have suggestions
no your code is fine as is, I am just being pedantic
Thank you for the pointers, I'll look into it!
i'd like to not use old api but is it possible
the fact that the new APIs are more annoying to use justifies using the old ones lol
is OrderedProperties a class of your own
yes
air is not null
its an empty item stack the only place where items are really null is the inventory which is just legacy ick
Air is an ItemStack with the type air
yes Empty Item stacks are empty not null see ItemStack#isEmpty
yeah i was using that but is curious
its just nicer than having null
i would prefer null tbh
sadly for you the API moves in the polar opposite direction
yeah i was looking that
yeah offhand is notnull and equipment can be null lol
checking if something is null is alot easier to do and looks cleaner imo
how is it a lot easier tho? its the same amount to write?
if (itemStack.isEmpty()) vs if (itemStack == null)
and its easier to do if you just wanna check the type
if (itemStack.getType() == Material.STICK) vs if (itemStack != null && itemStack.getType() == Material.STICK)?
it is easier because you don't have to guess whether it is null or empty
if it is non-null then it can only be empty or whatever type you're thinking it is. If it is nullable it can be null, empty, or another type
Yeah, old api is null new is not null. Maybe once asm utils is finally here there could be a possibility to finally make it all not null
When api is returning nullable item it's always a non-empty to not break the old plugins
yeah, I just meant its not a lot easier to check if its null, [like polar said](#paper-dev message)
question, can a bukkittask be cancelled if its scheduled to run later?
thanks guys
You can just do Objects.requireNonNullElse(/some getter/, ItemStack.empty()) everywhere for now to normalise it to not null
cursed
das alotta allocations
Luckily that's something that java is designed to deal with
didnt care
It's just a wrapper around 3 null fields for a method that java knows pretty well how to inline and avoid allocation
when i do 3 more allocations on tick which has 100k allocations π
I personally always use new String(new String(βhiβ))
i do Optional.of(new String("hi")).map(String::toUpperCase).ifPresent
just for the love of the game
Always wrap your literals so they are literally new
new String(new String("hi")).intern() is way better
That is true
Intern strings? All my strings are seniors.
I don't hire strings in the first place
they don't work as efficient as humans
even if the string is a senior
interns? thats too much legal liability, I just contract my strings
-# anyways this shouldn't be in #paper-dev
Not true. Just yesterday, I got air in one of those nullable inventory event methods.
some inventory stuff does
its again all inconsitent
it's always a non-empty
I was just throwing it out there, in case anyone were to take his statement literally.
wait until you see the rest of the game
Is there a method to make a villager hold an item like they do when you hold an item they trade for?
Also is it possible to make mannequins move like mobs?
If I wanted them to swim like a drowned or attack you like a zombie.
you can make their hand swing but only that, don't think they support swimming position
Mannequins were designed to be like players without the actual player, so I'd imagine so
If they can't then maybe not yet but I'm sure it will in the future
you can set their slot 0 for that I believe
@dawn kiln nevermind, I was wrong
they support all the standard poses
I guess only sitting is left out
But how would you make them move?
by teleporting them
With proper pathfinding.
same deal
you just use teleport instead of Pathfinder#moveTo or whatever
it is more manual
I feel like there has to be a better way than constant teleporting.
there is not because mannequins aren't pathfindable mobs
Could you just copy a zombie's nms or something into a mannequin?
you could disguise a zombie as a mannequin
but at that point why not just disguise it as a player
Just saw this and it scared me too. π
is there a way to do different quick action dialogs for different players?
Are there any guides on doing this?
why player.teleport can return false?
im removing the vehicle before
oh wait i just added a new dumb TeleportEvent somewhere else that should be the reason!
That flag doesn't do anything
not really, but there's Lib's disguises
which I would recommend using rather than trying to do it yourself
did they improve performance? last time I tried it was surprisingly heavy
its not particularily hard to do yourself, extend the NMS mob, override the entity spawn and entity data methods, done
im trying to spawn an area effect cloud with no particles and im struggling, i see that gsit overrides the tick method but i had a read of AreaEffectCloud#tick and #serverTick/#clientTick and it doesnt make sense for this to prevent the particles
ultimately i want to avoid nms
lol i figured out a way that works for me but still confused by overriding tick working
The answer for individual per player behavior is mostly packets
why are you trying to spawn that
an invisible area effect cloud for what

