#paper-dev
1983 messages · Page 2 of 2 (latest)
Intellij sometimes is just dumb
Is there a way to open another inventory without closing the first one? Like when you click an item in the inventory, it will open another inventory and when closed it will return me to the old one
Without manual work
no
its not hard to store a stack of open menus 😭
if you control the menus, sure, but if you don't then it gets iffy
we even have a button util around it
I store the history in my GUI library too (but only of GUIs created through the library. Vanilla inventories or other plugins would not be easy to support automatically)
oh yeah not at all
yeah, all the custom inventories my plugin is managing are created by it
is there a way to check which player used the campfire? CampfireStartEvent doesn't report on the player who started it, but i think the player is the only entity that can cook on a campfire, so idk why its not included in hat event
you can probably just use the interact event
yeah that was my second thought, just wanted to make sure there wasnt another way
What causes CustomBossEvents to be stored on a world's level.dat file. Deleting all bossbars from Bukkit.getBossBars() doesn't result in them being removed from any actual file that I can tell
why are you an app? i know that this is a user bot, but why xD?
@halcyon briar @tulip urchin
what version?
because since the storage format change, those are no longer stored there, and when upgrading from a previous version they are moved out into its own file (data/minecraft/custom_boss_events.dat) and removed from the level.dat
Is it better to create a runnable that executes after a set amount of ticks, or make 1 runnable that runs every tick and waits for the correct time?
For context I am trying to create an animation to chest GUI.
depends on how high the frequency is
in which you would have to schedule new tasks I mean
also is the animation important enough that you need to decouple its framerate from your server's tick rate?
It's a library so can't tell how it'll be used in the future (the frequency can be changed when building the animation freely). Could be as often as every tick, but I don't think anyone would even notice the changes at that point..?
true, I might need to use some other way if I want to go faster than 20 ticks per second.
but wouldn't that create a lot of packets for changing the inventory? (would that even be an issue?)
I mean, that would start being an issue once you go over the network speed of the server xD
also it sounds like you expect changes every "tick" so a task timer would be best for that tbh
I have no idea how much bandwith updating a single inventory takes
you could potentially do some extra calculation to see if the next frame is very far in the future and cancel the timer and schedule a task but I doubt it's worth it in most cases
yeah the question was mostly if I should keep everything on 1 timer, or make multiple and let papermc handle the timing
yeah it's supposed to be in-between animation for GUI, so just visual animation. Should be no reason to have frames that last more than 1 second.
ig I'll just keep everything on 1 timer, since that's probably the cleanest in terms of the logic and performance anyway.
If the Minecraft server and the website are hosted on the same VDS and both are public, what is the best way to set up communication between the website and the server? How can we ensure that players purchase in-game items on the website and receive those items on the server? Data exchange between the website and the server must be two-way, meaning the Minecraft server must also be able to send data to the website at any time. What would be the best approach?
weren't you suggested to just read/write to the database directly, like, two days ago?
or yesterday
Rest is probs fine
I'd like to hear more opinions
Or that not sure what your entire problem is
1.21.11 in my case
you can't get rid of the section entirely i don't think, but removing the persistent bossbars will empty it for sure
Hi, is there any clear way in papermc api to disable invulnerability ticks (3 seconds) on join? Doesn't appear as if noDamageTicks, and it appears like setting isInvulnerable = false right before player.damage(n) has no effect either. The only source I found on this that had any helpful information was a spigot forum post from 2012 pointing at NMS
I'm trying to prevent rejoin exploits as well as immediately deal damage to the player from combat log functionality I've implemented, but it doesn't seem possible, as the server insists on forcing the player to be invulnerable
i dont think there are many other ways besides using a database as a way to pass information between the server and website
I thought mojang got rid of invulnerability on join
you might need to collect them into a List first before removing them however, otherwise it might throw a CME
since when
Yes, I want to understand which is the best
I know they got rid of it in a snapshot, I want to say 1.20?
in my checks with runTaskLater, it still seems to be 60 ticks until isInvulnerable gets set to false; in that period, I cannot disable it whatsoever
Maybe it didn't stick though
hmm
I'm on 1.21.11, and player.damage does nothing unless I wait ~60 ticks, shrug
Easy workaround for the combat log stuff, just kill them in the quit event 😄
You tried to escape battle, you lost
Even easier fix: pvp=false
that property got turned into a gamerule semi recently
Heya, does Entity#setVelocity(vector) not work on ItemDisplays?
ItemDisplays can't be moved iirc
Displays basically kinda don't tick on the server, so no
yeah
What data component type manages attack cooldown?
just resorting to recalculating damage application math and applying health reduction manually, it is what it is
isn't that just the attack_speed attribute ?
Okay, that sucks. I have the following problem:
- I want moveable ItemDisplays as part of player controlled vehicles (think cars, helicopters and such)
- I'm currently teleporting the display every tick to make everything work (works as intended)
- Sadly, depending on some random things (I suspect connection speed and latency), the entity visually rubberbands for some players (vanilla and modified)
It makes the whole experience much worse, before the switch to display entites we used armorstands, which still rubberbanded, but much less.
Any ideas or suggestions on how to improve this are welcome
you'd add an attribute modifier for that attribute to the item if you wanted to control it
maybe plugins like essentials
they do that
yeahh I could read source code
ah, yea, attack cooldown is 100% attributes, I don't think that there is something else there, you'd need to add an attribute to offset the players own attribute value
I mean, there is a component to apply attribute modifiers to a item, yea
that's where you store attribute modifiers for items, yes
There is just no direct means of setting a value
it's marked as an experimental api, but I do it like this, I think that's what you want:
override fun applyModifierInternal(name: String, item: ItemStack, value: Double) {
val builder = item.attributeModifiersBuilder()
val slot = item.type.equipmentSlot.group
builder.addModifier(
Attribute.ATTACK_SPEED,
AttributeModifier(
getNamespacedKey(name, slot, "attack_speed"),
value,
AttributeModifier.Operation.ADD_NUMBER,
slot,
),
)
item.setData(DataComponentTypes.ATTRIBUTE_MODIFIERS, builder.build())
}
paper plugin dev first step: disable experimental warning for project
Does setting the assetId actually change the itemstack's item? For example would changing a itemstack with no attribute modifiers asset id from a netherite helmet to a diamond helmet change the armor points?
the asset id only affects the visual model
it doesn't alter the equipment mechanically
bump
- It seems like every entity except the entity the player is riding is lagging behind
You could try to sync it by using PlayerClientTickEndEvent
declaration: package: io.papermc.paper.event.packet, class: ClientTickEndEvent
They'll always lag behind unless they're mounted to the player somehow
You can potentially do tricks to minimize that but you can't make it smooth no matter what
you can mount display entities onto something (marker armor stand would work) and move the armor stand with velocity
tho not sure if marker armor stand ticks, but you get the idea
I think we disabled armorstand ticking
The way I do display entity animations is that I add the display entities to the player itself (as a passenger), which means that client-side, for every player, the entities move together with that same player
You simply need to transform all of the displays from the player origin, which requires a bit of math, but it's doable
but still, just mount it and move the vehicle entity
I've made a couple of such display-based animations, even very complex models, and this is always my go-to way, it works well
The "texture" entity and "seat" entity are different, so I don't think this is possible in my current setup
Why wouldn't it be possible?
You can have more than one passenger mounted to a player, no?
Yeah ^^
Don't make the player mount the entity, make the entities mount the player
Other than the seat I guess if you're looking for vehicle controls
What if there are multiple seats? I don't think I can mount the texture to all of the players
In that case I would just say mount it to the primary player (like the driver) and give the other players corresponding velocity to the main one
It might look a big janked, but it will definitely not rubberband
you may also play around with per player entities and packets
That could also be a possibility, though that would add one more dimension to the transformation of the displays
Not a big deal, but can be a bit hard to get right at first
like, create the helicopter entity for each player, offset them per the player, and then mount the other passengers client-side with some offset tricks
... I have to get some paper and draw this lol
Are you using a boat or something? is the player in control of the vehicle (i.e. the first passenger in a boat even if noai is set on the boat)
or a minecart, apparently minecarts interpolate over 5 ticks instead of the typical living entity 3 ticks
anyways... ping me for client interpolation questions. i've dealt with this code a lot
Nope, all ItemDisplays
Very crude paint thing
When the main thing is teleported, every seat recalculates its new target location by using the new main location and adding the offset
Controls use Player#getInput, which in turn are parsed into custom vehicle control events, which in turn are checked on the driving manager thread to adjust the new location of a currently active vehicle
is the player mounted on the itemdisplay, or the itemdisplay mounted on the player?
Player on the ItemDisplay
how do luckperms auto detect permission nodes? do they hooked into haspermission check or what
Yeah, the permission vault is composed of both every permission checked during the current runtime, and every permission already set on a player/group.
i can look at it later today, but the player mounted on a non-player controlled vehicle shouldn't affect is interpolation in any ways
Thank you 
sprites, see the object component
this right?
yep
thank u
when were sprites added (as in mc version) ? and how exactly would this typa sprite look on older versions before sprites existed?
was fairly recent, and well, idk how handling of invalid/incompatible components works
1.21.6 I believe
I think it sorta just ignores them but I might be wrong on that front
Are you sure that you are doing it right? I asked codex to simulate this for me using a headless client and it's returned that mounting a player on a display entity didn't affect it's interpolation. The most likely scenarios are that you didn't set the interpolation metadata to be the same on all of the item displays, or are somehow moving/updating the item display the player is on differently than the other item displays.
So that pre creature spawn event fires for all natural spawns?
Yes
I had no idea. That will be a huge help for me. Thank you.
Like it says listen to the normal one too but if you block at the pre event the regular one won't even happen
And the pre one is more efficient
I'm pretty sure I'm doing it right. It's not always lagging behing, just sometimes. Sometimes, a restart of the server causes this problem for some players to appear and for others to disappear.
Entity metadata:
// Main
itemDisplay.setInterpolationDelay(0);
itemDisplay.setInterpolationDuration(3);
itemDisplay.setTeleportDuration(1);
// Seat
itemDisplay.setInterpolationDelay(0);
itemDisplay.setInterpolationDuration(3);
itemDisplay.setTeleportDuration(1);
It's still a bad idea to use events to block spawns rather than turning down mob caps and such, this just hurts less
I have a per player monster spawn toggle they can use. I don’t have any other option.
Oh it seems I was already using that event. That sucks. No performance increase for me today.
declaration: package: org.bukkit.entity, interface: Player
Exactly what method am I looking at?
setAffectsSpawning
But then they lose animal spawns as well.
Animal spawns don't really happen, they're a myth 😛
Unless you're doing it on purpose
I have mine increased.
worldgen spawns are pretty much guaranteed to put you over the stock limit and breeding farms will keep you over the limit even if you kill off the rest
Would that setAffectsSpawning create a significant performance increase over just canceling the pre spawn event?
iirc the spawning loop starts with players, not chunks
So you'd just skip that iteration of the loop entirely
I’ll look into it. I tried using that method once and stuff was spawning anyways.
I dunno, read the source code
Yea I’ll look into it when I get a chance. I hope you’re right.
most work is determining if location is spawnable, preSpawnEvent has location in the constructor, therefore you're not really avoiding most of the work
yes, it's better than canceling normal spawn event
but still ideal way is to not have all those lookups at all
when it occurs for a player, does it permanently occur for that vehicle? If so, then the issue lies with the item display metadata being lost somehow. if it occurs until the vehicle stops moving, then you aren't sending these packets close enough together or in a place that ends up delaying some packets between the client's ticks, basically splitting when the client knows it should interpolate the display entity. If it's the later, you can use a bundle packet to force the client to process interpolation in all the same ticket to ensure that all display entities interpolate the same way.
bundle is simpler than bundle delimiter to deal with
or otherwise update all displays at the same time on the server such that the packets are sent close to one another. don't update the one the player is on, then start calculating how everything else should behave. Calculate first, then send all at once
I'm not calculating packets, I'm actually spam teleporting everything using Entity#teleport. Currently, the main entity is being calculated and teleported first (necessary so the seats know the new « center » location), then all seats are looped (max should be 15 on the huge bus)
Vector movementVector = vehicle.getMovementVector();
Location resultLocation = mainStand.getLocation().add(movementVector);
resultLocation.setYaw(vehicle.getYaw());
if (!mainStand.getLocation().equals(resultLocation)) {
vehicle.setLocation(resultLocation, false);
VehicleUtils.setEntityLocation(mainStand, resultLocation);
movedVehicles.add(Pair.with(mainStand, vehicle));
for (VehicleSeat seat : vehicle.getAllSeats()) {
if (seat.isSpawned()) {
VehicleUtils.setEntityLocation(seat.getEntity(), seat.getAlignedLocation(vehicle));
movedVehicles.add(Pair.with(seat.getEntity(), vehicle));
}
}
vehicle.addDrivenKilometers((float) (movementVector.length() / 1000f));
}
That's basically all the movement code, getMovementVector() checks for collisions/terrain/.... setEntityLocation is from a time when you still needed the special flag to keep the passengers
Whats the current method to remove this when display name is empty? ItemFlag.Hide_Attributes?
you can just hide the tooltip entirely
See the tooltip display component
ItemMeta won't work for that
(ItemFlags are especially deprecated)
ahh okay, thank you!
My next guesses would be that entity tracking works differently for a mounted vehicle than a non-mounted entity, but I don't remember this being different. If you see this only when mounting and moving immediately, the server might send something to the client upon mount to ensure the position is correct. I could tell what's going on with a packet log of the vehicle and these packets.
SniffCraft time! I feel obligated to mention this just due to its name
make sure you are on 26.1 though, I remember a bug related to display entity passengers and the interpolation being fixed there just recently
Ahhh, that could be the issue. Server is not on 26.1 yet, but very soon
why SniffCraft isnt a paper fork that only allows sniffer entities
damn <@&748618676189528155>, ty!
Why is it, that whenever I try to schedule a task, it throws an error saying my plugin tried registering a task while disabled, even though from what I can tell the plugin is enabled. I am very new to this so sorry if I'm missing something really obvious
[23:00:24 ERROR]: Could not pass event PlayerJoinEvent to Swagmobo v1.0-SNAPSHOT
org.bukkit.plugin.IllegalPluginAccessException: Plugin attempted to register task while disabled
Did you do it from your plugin's constructor or onLoad method?
You have to do it from onEnable or something called later than that
I scheduled it inside of a PlayerJoinEvent.
server logs?
I mean, the thing is fairly explict in how it checks for a plugin being disabled or not
No you didn't, your event handler never got called
Although thinking about that more if you were able to register the event handler that means you at one point called the register at the right time but your plugin got disabled later
But it didn't get disabled the normal/right way since it left stale event handlers behind which sounds like something hacksy is going on
⁉️😭
In the logs it never showed that it had been disabled and also still shows green in /pl
message.txt by @granite latch: https://pastes.dev/N1ZZNT6ddi
are you using the bootstrapper?
All I can think of is that your plugin instance somehow became null
If you don't specifically need paper-plugin features (registry editing), I would stick to normal bukkit plugins for now
package gg.justservers.swagmobo;
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
import org.bukkit.plugin.java.JavaPlugin;
public final class Swagmobo extends JavaPlugin {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(new TestListener(), this);
this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> {
commands.registrar().register(GuideCommand.createCommand().build());
});
}
@Override
public void onDisable() {
// Plugin shutdown logic
}
}
Oh you did make it to the event handler, I'm clearly too Friday'd out for this conversation
and the code for the TestListener?
im scared to release ts 🙏
The fact that you don't pass in the plugin instance to the test listener screams that you're probably calling runTaskLater with something totally wild instead of your plugin
yeahh
oh they probably do new Swagmobo() in there
Is there a way to restrict access to the creative mode inventory? I basically only want to allow them to use specific blocks and not have access to everything.
nope
the inventory is entirely client-side, its a glorified /give command
you can use the InventoryCreativeEvent to cancel item creation, but that will look very buggy to the player
This guy is trying to code in Java
-# Edit for context: I know swagmobo, he's one of my mods
I am impressed
How did I know you were going to end up finding this.
Look, it's not like I am inactive on here
At least I gave it a shot, eh?
I would've probably ended up answering your question if I had seen it earlier too
You seem to be doing quite well though
Constructing a new plugin instance is not an unheard of mistake, that can happen, don't worry about it
Frfr? 😭
Well, commands, for example, are a topic some people seemingly cannot wrap their heads around, most notably with brigadier
You have knowledge from it from Skript, sure, but the Java side of things can still turn out relatively complex
Yeah I did notice that, xd.
Were the Paper docs helpful at least?
As your lawyer I advise you not to answer that question.
I make joke. Strokk is docs team.
Could barely have done this without them ngl, so I do wanna say thanks to you and the rest of the docs team lol
How tf did it just take me 3 attempts to select the correct emoji what am I doing
i find the paper docs very helpful personally though i wish they had more constructive and building content (def opinionated though)
like, maybe they teach you to make smth a lá the rust book’s example projects, eg a kitpvp plugin or a simple skyblock plugin using modern papermc best practices
i say that since while i thinm the docs do a great job telling you about the breadth of content, you’re sorta left on your own to compose them in my experience
and since many ppl getting into mc modding are learning how to program alongside this, it might be nice to give pointers
they are good docs tho im a fan
I mean, that would more be an example repo rather than something that really belongs in the docs
otherwise you basically end up writing a course, and that's more sorta full time "I get paid for this" levels of dedication
yeah that’s fair tbh
are there particle libraries that have built in effects
EffectLib does
I'm getting a very weird issue. I've been thinking it was an error in my own code, but after a lot of messing around I'm starting to think it comes from Paper.
My server is running the latest version of Paper (26.1.2 65-stable) and my plugin has the exact same version in dependencies
I put a stack of 64 white wool in a chest in slot 0, nothing else in any other slot.
When I get the source inventory from an InventoryMoveItemEvent and log the result of getContents() to the console, I get this
[ItemStack{WHITE_WOOL x 1}, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]
It clearly says there's only one white wool in the chest, even though there's clearly 64.
Is this the intended behaviour or did I actually find an issue?
I'll also add that if I put any other item in the chest in any slot, it suddenly goes back to saying that slot 0 has 64 white wool
What did you test this with? Hoppers?
Yep
it's how I discovered it, I was testing my filtered hoppers plugin I've been maintaining for a while
I was able to reproduce it. Dropper > Chest seems to work fine
it was chest -> dropper
should've specified that at the start, mb
so chest > hopper > dropper?
So, apparently this is intentional. Right before the event is called, the count of the ItemStack that is about to be moved is changed (Math.min(level.spigotConfig.hopperAmount, originalItemCount)). ~~No idea why this is done tho. ~~You could change the hopper-amount value in the spigot.yml config to 64 to "fix" the issue.
this is in net.minecraft.world.level.block.entity.HopperBlockEntity#hopperPush
that's kinda annoying for me though, since not all users will want their hopper amount to be 64 at all times
It happens for both hopper push and pull actions
could you tell me exactly where this is done so I can try finding a solution, or atleast try knowing why they do that?
net/minecraft/world/level/block/entity/HopperBlockEntity.java:271
thanks
hopperPush and hopperPull are both part of the hopper optimization patch, and I may not 100% understand all of the changes. But, changing it so that we copy the original item stack into the moved item stack (so no mutation of the underlying container when changing the amount of the moved item stack to Math.min(level.spigotConfig.hopperAmount, originalItemCount)), allows to properly read out the inventory contents of the InventoryMoveItemEvent. From my testing, this doesn't break anything. This wouldn't help you for now, @warped coral, but maybe it's something that can be changed to fix the issue with the event.
I found a work-around by reading the code, I realised that if it returned 1 (hopper amount) then it meant it was the first occupied slot in the inventory, and when it is, instead of using inventory.getItem(slot).getAmount(), I could do event.getItem().getAmount(), which would give me the right amount
aaaand nevermind
That's nice, though I think that's still something worth looking into because InventoryMoveItemEvent.getSource() currently does not return the actual inventory content of its source (at least that is for hoppers)
I wonder, is it the actual inventory or a snapshot of it?
the actual I believe
dang
if it was a snapshot I would've gotten the location, block, blockstate, tilestate and then its inventory
I have thunk up a new work-around
instead of using my own logic (which was meant to work-around Minecraft's logic of checking only the first occupied slot, which I needed it to check the entire inventory for my filter to properly apply instead of getting stuck), I'll revert to normal minecraft logic when it's the first occupied slot
how can I prevent entity moving at all like set its AI to false?
is cancelling the entity move event enough?
Have you tried, uh, setting AI
and thus my plugin worketh
I don't want to really disable the AI
that's why I ask
What do you want from its AI that it can do without movement?
maybe messing with mob goals might suit your use case, you could remove their pathfinding goals
"maybe" could be avoided with a clear explanation of the XY
nvm, found an existing issue for this https://github.com/PaperMC/Paper/issues/9028
I'm making a custom gui and it gets darkened, what is the cause and how can i fix it?
Set the color to white
By default titles are gray
is there a "time since last death" i can check for Player? thought maybe getTicksLived would display that but it doesnt seem to get reset on death
there's a time since last death statistic
MenuType.MERCHANT.builder()
.merchant(villager)
.checkReachable(false)
.build(player)
.open();
When I open a menu for the player like this, the villager’s reputations don’t work. Is this a bug, or is there another way to do it?
there's like a pixel of a black line, what might cause it? the texture itself doesn't have it, and it's not the default gui under it
Make sure the title isn't bold or with italics
bro u might be my life saver
:(
Seems like not at the moment, open a feature request issue
Hey if you open an issue and explain what that is i can get around to trying to fix this for you
Thanks a lot 🙏
what is the bukkit representation (probably enum) of humanoid arm (left or right)
Thank you for trying to solve it 🙏
Are you looking for EquipmentSlot or something else
the bukkit representation of net.minecraft.world.entity.HumanoidArm
maybe Hand?
?
There very well may not be one
it's used in the protocol to tell the server which hand the player has selected for main hand
none?
declaration: package: org.bukkit.inventory, enum: MainHand
Found it not sure if this is what yoh want
I think it is
Heya, how do I get the path to the world folder itself? It used to be World#getWorldFolder#getPath, but now it adds ./dimensions/minecraft/overworld/ to it
Hey is paper anti Xray good and how is it different from others?
It's pretty good, and it depends on the anti-xray you are comparing it to
Double posted. Continue X-ray chat in #paper-help
Thank you 
-# ~~Is there a way to dynamic utilize something like that but on a per player case? I guess the best way is to build a complete tree but just for the one player as executor permission? And with that, I currently don't see how I would get the dispatcher - ~~
-# Nevermind, I just steal store the commands dispatcher from the lifecycle until I find the api method to get it later since I can't use the commands instance. Removing also works when you finally don't always use the wrong name ^^
-# The only problem is that the console can't use the command (it is not registered in the bootstrap phase) but at least players can /execute as them.
However, I got an actual issue I thought I had seen on GitHub but can't find it:
getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, commands -> {
commands.registrar().register(Commands.literal("getPlayersName")
.requires(stack -> stack.getExecutor() instanceof Player)
.executes(context -> {
final Player executor = (Player) context.getSource().getExecutor();
assert executor != null;
context.getSource().getSender().sendMessage("Players name: " + executor.getName());
return Command.SINGLE_SUCCESS;
}).build());
}
);
restults in
[14:11:00 ERROR]: Command exception: /execute as @n[type=!minecraft:player] run aethosevents:getPlayersName java.lang.ClassCastException: class org.bukkit.craftbukkit.entity.CraftArmorStand cannot be cast to class org.bukkit.entity.Player (org.bukkit.craftbukkit.entity.CraftArmorStand and org.bukkit.entity.Player are in unnamed module of loader java.net.URLClassLoader @179d3b25)
So either I messed up with the tree or the execute really does not care about the requirements?
That's very fun
I do have to say that I have encountered similar before. In my cmd lib I actually double-ensure executor validation by putting in the instanceof check inside the .executes method as well, just in case something goes wrong
I do not know what causes that behavior though
Yeah ok no, Inverting the condition lets me use the command from the console and executes it correct.
`> execute as TheosRee run getPlayersName
[14:19:30 INFO]: Players name: TheosRee
getPlayersName
[14:19:31 ERROR]: Command exception: /getPlayersName
java.lang.NullPointerException: Cannot invoke "org.bukkit.entity.Player.getName()" because "executor" is null
`
I think you only can depend on sender check and not also on executor checks
Pretty sure you can do executor checks
Yeah but idk how much it's made to take this into account, since vanilla only checks the sender
So much to my idea to complete ignore target player by just use execute as <player> and use that in the commands -.-
Well, at least the perm checks are done correct for the sender which is the important part there.. mostly
Well you can still check that in executes, the requires is way more to completely hide the command from the player without permission
See, works fine
idk, brigadier is often weird with non-vanilla usages
To me it smells more like the /execute as is being problematic here
what if you register during bootstrap
Me?
https://jd.papermc.io/paper/26.1.2/org/bukkit/Registry.html are all of these modifiable via paper plugins?
declaration: package: org.bukkit, interface: Registry
no
no
Very interesting for sure
It seems /execute as @e[type=!player,limit=1] run only-player from the player actually might've run it for the non-player entity
Since no error message is present
Or it is still passing the initial context in the requires and not the updated context
how do i know which ones are
But then it would've run it for my account? Which it didn't
iirc the ones available in RegistryKey
The ones that are deprecated
In the registry class
Just print into logs what is the executor in requires every time
^ these are the ones you can actually use in the various lifecycle/registry event
But most of those aren't modifiable
To that
-# The only problem is that the console can't use the command (it is not registered in the bootstrap phase) but at least players can /execute as them.
- the console can execute it but the player as executor requirement breaks it in my example :)
I am actually not able to get any debug debug logging in the .requires method for some reason
Like none at all
Oh now it worked
But only for the console
Oh nevermind, I am just stupid, I misplaced me sout call
(it only caught it if no player was present, duh)
Yeah so this is interesting
That smells an awful lot like unintended behavior
More like "this doesn't touch vanilla so it doesn't matter"
It's still a bug?
It pretty much is a bug?
At least way more a bug than removing the commands from the dispatcher results in them no longer in the tab complete but still executable :/
-# not related to the execute issue
Yeah, but unlikely that it's gonna be fixed, especially since looking at it, the parsing is done completely separately from execution, so the as takes effect after the whole chain is done. This is most probably a big rewrite to fix it
So the execute passes its current executor/sender to the other command before resolving the as part?
This then gets denied and nothing is done.
Something like that
Kinda understandable respecting the existence of @e..
-# performance wise at least
Yeah it would kill the performance to recheck this all for every entity
Would it?
Considering that it may run on thousands of entities that's a significant additional load
I don't think running one predicate more or less will change the outcome by a lot if you run some command for a thousand entities
Yeah but I feel like the command itself will be much heavier
And also that it may end up resolving to a different node otherwise, which wouldn't be available for the recheck anymore
More like, you would need to evaluate it for each character?
Like at that point you are not bottle-necked by running one predicate
At least for the tab complete part
Yeah to properly make this work you would need to reparse the string for every entity from the thousands
The requires predicate is not evalutated during tab completion, only when a the command tree is send to the player (where they are put as the executor) and when a command is ran
Sounds like expected behavior to be honest :/
Considering that datapacks exists and vanilla doesn't need that it's optimised to not do that
Ah okay, for the tab complete part understandable.
Not for the part when it actually executed, tho.
It's much faster to parse the command 1 time at datapack load and then run it with different executors
Would you?
You already have the nodes, lol
Do you at execution time? I don't think parsed context has them
You just construct a different CommandSourceStack (as is already done, considering the .executes correctly uses it) and re-check each node's requires predicate with it
When you run /execute as @e run my-command, it's parsed into nodes once, and then you can do the additional logic on it (such as the .fork stuff from the executes method, or requirements), that's how I'd do it
There's no need to re-parse the same thing a thousand times for each entity
Unless I am massively misunderstanding you here
Different executors = different nodes to parse, you can't preparse them as 1 difference and you have a different tree
But when I have one node that requires a player and a same named one that only works without? That would break then when I interepret what you wrote correct?
Why?
Also I feel like this is way beyond what should be in this channel
But why would having a different executor change the node output from parsing
Because, in your example, one time a node is available and you can check it, another time it isn't
Every time you need to recheck the string to make sure that you consider all further nodes
Why can you not parse the nodes with the assumption that the predicates match, and only afterwards check them
commands.registrar().register(Commands.literal("newCommandAtRuntime")
.requires(stack -> stack.getExecutor() instanceof Player)
.executes(context -> {}
.requires(stack -> !(stack.getExecutor() instanceof Player))
.executes(context -> {}
like that
-# edit: yeah, that does not work at all as it gets overrriden even when defining the literal multiple times
That's not how that works?
Yeah, that is shortened with the actual node name, it was more for the visual
I often find putting player executor requirement in requires predicate to be useless, given that /execute as exists
The predicate values change per-executor, sure, the predicate instance does not
You need different errors. For example one player can teleport only to coordinates and another player can teleport to coordinates or at the player, both of those ways have further literals. You will need to reparse the argument to know which literals next to parse
It's a huge headache that vanilla doesn't need. Plugins can just properly check stuff in executes
Maybe the one time I could see this being a problem could be something like this: ```java
Commands.literal("cmd")
.then(Commands.argument("for-op", word())
.requires(source -> source.getSender().isOp())
.executes(...))
.then(Commands.argument("for-non-op", word())
.requires(source -> !source.getSender().isOp())
.executes(...))
But that's also kinda oddly specific
I have never encountered a situation or heard of another person who encountered a situation that would require something like that
But that's also kinda oddly specific
In the eyes of brigadier that's same thing as depending on executor and not sender
But isn't it much more problematic if we assume that the /execute as will leak the predicates here entirely?
Even if we were to re-parse the command string each time, I doubt that the problem will be in the performance of the parsing logic
As I said, mojang considered vanilla, and there the command can be parsed at server start before the world even exists with the necessity for it to be as fast as possible at processing every entity in the world every tick multiple times. In the eyes of brigadier you should only care about sender and command there
If you just add revalidation of requires in execution that could already add tons of overhead to small servers that has something like incendium
Because it spams thousands of commands per tick in a normal world
it's not purely gen datapack, it has a ton of functions
But do all of those commands contain /execute ... commands?
Yeah
In a datapack almost every command is an execute one
Commands are ran by default with no context like an entity or world so they need to get that
Are you sure though that no parsing is done in runtime when a command is executed?
I don't know much about datapacks, but I know that the requirements are checked for console commands each time they are ran as well
I could very well see that datapacks commands have to go through the same fate as well, as predicates, even if only checking the sender, can change during server runtime
I mean, my "fixing" suggestions is just something like this:
execute at 25 0 25 as @e[limit=2] run tp ~ ~2 ~
│ │ │
│ │ ├ executor: sheep, loc: 25 0 25
│ │ └ executor: pig, loc: 25 0 25
│ │
│ └ executor: none, loc: 25 0 25
│
└ executor: none, loc: default
Whenever a fork, redirect, forward statement occurs, the next nodes are simply parsed with the new source stack objects, it's not like the information isn't already present.
This would also mean that for a command, which doesn't do any multi-target forking, the parsing speed stays exactly the same
And it's only the next nodes, which are forked, that get parsed multiple times, not the full thing
Yeah, it's stored in https://mcsrc.dev/1/26.1.2/net/minecraft/commands/execution/tasks/ExecuteCommand, in the command context
But then don't we run into this being a huge problem again?
Yeah let's leave the discussion at that
I know you wanted to move on a while ago, I apologize for continuing
I want this in jap(u)
Are there any recommended GUI libraries?
there are a few that come to mind like InventoryFramework, Triumph, but honestly its less "standard" than just using a command library
Gotcha. Figured I'd see what we already have available instead of rolling my own and missing edge cases. I'll take a look at those first though, thank you!
I also have my own tiny ass command lib I use personally https://github.com/Y2Kwastaken/MenuKit uses a more modern API, than the others, but I think arguably it could be a tad limited depending on your use case.
i'm surprised y2kwastaken wasn't taken
I'm just looking for a simple item interactions + an anvil rename interaction. I don't mind implementing the anvil action myself though. Your lib and Triumph are strong contenders rn, thank you for sharing it!
Oooh, you have support for Anvils
Well that makes the choice easy
If you need anvils for text input maybe consider dialogs
Oh yeah, that is a thing
I need my stuff to be Geyser compatible though, so I may or may not make that choice
fyi, geyser supports dialogs
...it's time to reconsider a lot of choices I was going to make then
Yeah geyser automatically maps them to bedrock forms so you mostly shouldn't have any issues, but you'll need checking as it's not mapped 1 to 1 so you'll need small tweaks sometimes
hi guys im a bedrock server developer and i wanna set up a paper server to learn to make plugins and such can anyone help me start?
ive never played java btw
To create plugins, learning Java beforehand is like learning how to write before creating a novel - it's an essential part of the process.
There is no shortcut to learning programming, just as there is no single, definitive way to approach it. Everyone learns differently. One of the best ways to learn is by doing and actively applying what you're learning as you go.
Learning Resources:
is there no way of detecting player right clicks whilst theyre consuming an item??
like i have an item thats being consumed i want to know if theyre holding right click
What else would they be doing?
they could cancel it early
player interacts only actiavtes on the start of the right click hold
But then it wouldn't consume the item..? I'm confused about your use case.
well im using consume item just for the animation
the item is a watering can
im using the bow pull anim
but like i want to know when the player is holding so i can release a stream of water
Regardless, you can use PlayerInputEvent or Player#getCurrentInput.
This is useful context.
thanks
does this not get the
Gets the current movement input, as last provided by the player.
it doesnt get right click no?
Ah right, I thought left and right were mouse inputs but they're left and right movement. My bad
all good
Hey all, I just got started with coding paper plugins recently and I am trying to make a really simple VoidGenerator for my Overworld and nether. I know how to extend the chunkgenerator class and make a VoidChunkGenerator Class, but how do I use it for my main world? :(
The only ways I have seen people make it work is making a new world with a new worldcreator object. But I want my existing "world" and "world_the_nether" to use this chunkgenerator, how do I do this?
If anyone could help me I would be very thankful
I knew there was one for it just had to search for the right keyword
ahh thanks
also is there a way to see documentation in intellij for setData
i have no idea what to put for the args sometimes
item.setData(DataComponentTypes.ATTACK_RANGE, );
like i dont know if this is expecting a float or something
The DataComponentType is generically typed with the class that should be an argument
And you would create that with the builder AttackRange.attackRange(), yeah https://jd.papermc.io/paper/26.1.2/io/papermc/paper/datacomponent/item/AttackRange.html
thanks
Can't you define the world generator per world in bukkit.yml?
See how Terra does it: https://terra.polydev.org/install/bukkit-server-world-creation.html#procedure
That'll set it without you having to create the world manually
Yeah you'll need to set it and then delete the existing world
ahh ok thank you so much
do i need to do something with the voidgenerator class in my on enable function too? or is having the class seperately enough
haha ok
i think ill find that out theres another papermc voidgen where the code is on github
thanks tho
This shows most of the steps I remember, not sure how out-of-date it is. https://bukkit.fandom.com/wiki/Developing_a_World_Generator_Plugin
this is actually a great resource thanks
guess i have to do this in onenable
or outside perhaps
BlockPistonExtendEvent and BlockPistonRetractEvent return List<Blocks>. How to get new locations of these blocks?
what was the name of the thing that i can set some persistent data to the player itself?
persistentdatacontainer?
does that support disconnect/restart ? 🤔
i usually use db stuff for that but i think i can use that now
yeah as the name states, it is persistent data
PlayerQuitEvent doesnt fire when server shutdown right, i'll just use onDisable() i think
Anyone has an Idea how to spawn in SkyBlock islands under players? How do you even go about this? Is there like a structure spawning command and u can add ur custom structure to it?
Can I register or remove commands during runtime?
my personal reccomendation is InvUI
The dialog API is great
How to make a CustomModelDataComponent Object and set it to the item meta of an item stack?
Just get the current one, if none exists it'll create a new empty component
I tried making a few interactions where if a player right-clicks with a certain item, the item is removed from the player's inventory and does something, however, when I put the item in my off hand, the item is not removed and I can just keep doing it forever.
Also, how can I remove just one of an item from the player's inventory because I just realised the method I'm using removes all of that item from the inventory.
You need to explicitly check if the item that you are expecting that is being used is in the main or the off hand, and to remove just one, you can simply decrease the count of the item stack
declaration: package: org.bukkit.inventory, class: ItemStack
This is the method for removing just one of the item. If the item count is 1, the item just disappears
Thanks :)
Can Bukkit.getWorld be called on any thread? No operations are done on the world beyond using it for a Location constructor arg
Ok i fixed it with Custom Model Data but idk why but my pivot (ItemDisplays) spawns not on the block above it spawns in the block
can you setup your environment so when you are debugging your plugin relocation is disabled, but enabled for production builds?
wdym?
i am talking about shadowJar relocation for dependencies. it breaks hotswap
what i've got inside the shadowJar task in my projects is
val disableRelocation = project.hasProperty("idea.debugger.dispatch.addr") || project.hasProperty("disableRelocation")
if (!disableRelocation) {
<relocations here>
}
in theory it auto detects the debugger but i still start the server task with runServer -PdisableRelocation=true
project.hasProperty("idea.debugger.dispatch.addr")
does this also work?
oh i didnt read
I use a think like
https://pastes.dev/ckDWyM3SrG for avoid relocate in debug
Dont remember where i found that...
Can I make the narrator of Minecraft say something to the person? Like send voice messages
That's client side, no
Can you load configurations such as a Configurate config inside the plugin bootstrap?
I dont see why not tbh
But you could send them a resource pack and play a sound from that pack
How can you make custom biomes with sky, water, and plant colors with a plugin?
you can't
well, not with the API at least, unless you were to just embed a datapack in your plugin (which is what most people do)
though main issue with it is that you have to override overworld gen for the biomes to show in your main world, and that is a lot of trouble
say you want to modify something about the biome, now you're stuck with the old gen
so, if you're gonna do it, you're going to have to do a lot of testing before putting it in prod
Is there no way to just change sky color?
I feel like there is probably a way with NMS.
Would it be possible to send a packet to a client to trick it into changing the sky color?
chunk packets refer to existing biomes for sky colors
how do i get for liquids when a player is right clickingliquid with player interacts?
at the very least you can send biome data for a chunk to the client now without resending the chunk
You still have to register the biome on the configration phase of protocol, you can't just start adding new biomes while the player is playing the game
Right clicking liquid? What do you mean right clicking liquid, you can't right click liquid
the only time you can do that is with a lilypad
i don't recall if the player sends an interact when right clicking without targeting a block as it's changed per version before
hm do i have to raycast then
would it be triggered as right clicking the air?
doesnt seem to be doing so
Player#getTargetBlockFace has a FluidCollisionMode parameter, that should do it
looks like that just runs a ray trace tho
getTargetBlock probably runs one too anyways
getTargetBlockExact also has that parameter too
this channel is for programming plugins, not finding them, sorry
You might have more luck in #general
in my code when players join the server, the packet responsible for sending the player's own GameProfile and the GameProfiles of other players is changed to send a different GameProfile#name
this PR seems to have changed how Player command suggestions are provided.
not 100% sure if this PR was responsible for the change, but this is as far as I could trace it going back through the src and commits. Version 1.20.4 was able to provide actual server-side player name suggestions, while in 1.21.4, the client receives the perceived names, from the initial packets it got when the client first logged in. why is this?
Probably because player names are recieved from mojang servers and UUIDs are what actually identify a player
idk how it all works though, but that's my guess
right, and that is what one would expect, but that is not the behaviour I am seeing.
for example, consider Player1, and Player2.
Player1 logs in. A packet is sent to Player1, changing their GameProfile#name to Play1
Player2 logs in. A packet is sent to Player2, changing their GameProfile#name to Play2 and sending Player1's GameProfile name as Play1
If player 2 does /minecraft:tp {tab complete here} they will see Play1 and Play2, instead of Player1 and Player2, which makes no sense to me
vs. 1.20.4, player2 would see Player1 and Player2, the actual GameProfile names, as tab completions
Maybe its just a change to give the server more control over the name of players.
which is exactly why the fake names shouldn't be showing up
The packet is being sent from the server, to the client with fake names
why would that then carry over to server-provided suggestions?
Why would the GameProfile suggestions not use the GameProfile names given by the server?
the GameProfile suggestions are generated from the server. the server itself has no retained knowledge that it has sent fake packets to change the perceived GameProfile of the user.
the line in red is the raw NMS code for the method that returned getOnlinePlayerNames(). these values are clearly being generated independently of what the client may or may not know
now my question is, why does my client NOW see the fake names in suggestions?
maybe its not a server change, but it's instead a client change
Did the GameProfile packets change their contents in newer versions?
If not, then it's just a change mojang made to the client, which we don't have control over with just the paper api.
cause the pr you linked has to do with preventing hidden players from showing up in entity argument selectors
if it's a client change then this PR probably doesn't hold up then
wait yeah its not a client change bc the command suggestions are controlled by the server
I still think that this is normal. It's weird that the names were different.
Player names aren't saved by the server iirc.
weird that real names were showing up in the first place? or weird that the fake ones are showing up now
weird that the real names were showing up in the first place. They should show what the server thinks the names are, not what they are
why do you think that would be anything but the real names?
a packet being sent to a player doesn't change any state on the server-side
it shouldn't, but you're talking about how it used to be different
the client has its own suggestions provider, my guess is that it is using that
and it just didn't before (or it didn't exist)
oh it does?
thanks! if you're able to check whether it was already included in 1.21.4, that would be great
ClientSuggestionProvider did exist back then, both in 1.20.4 and 1.21.4, only thing that has changed (aside from Paper changes) was the change to the gameprofile/nameandid cache, which from a quick overlook doesn't seem to have had an effect
guess I'll just give it a test myself to see if I can reproduce the behavior you're seeing
thing that has changed (aside from Paper changes) was the change to the gameprofile/nameandid cache
between when did you spot the change?
actually I got that wrong, the NameAndId change didn't happen in 1.21.4 yet, that was in the 26.1.2 source (I think this change happened around 1.21.7, if I remember correctly)
https://minecraft.katana-project.org/ you can use this page to decompile minecraft versions before 1.21.11, though it is a bit wonky since the file explorer shows the obfuscated names, you can still use shift + shift to search the actual decompiled class names (of course, you have to know what they're called)
Browse Minecraft's decompiled code in slicer.run.
there's also lynx's mache client repo if you want something local, though only for 1.21.1 and up: https://github.com/lynxplay/mache
I'll try to repro the issue and get back to you if I can find what changed since then
cheers for helping me on this.
yeah the easiest way to do it is just to listen to the server sending LOGIN_SUCCESS packet (this spoofs the gameprofile for the logging-in user).
and PLAYER_INFO_UPDATE (this spoofs the incoming GameProfile for users who are already logged into the server)
What would be the best way to modify specific tile entities (such as sculk sensors) when a chunk is generated?
huh
was this directed to me
pretty sure this is deprecated
tghank you tho
No, someone else came in
ah
Looks like getTargetBlock is deprecated, but getTargetBlockExact is not.
The deprecation notice for getTargetBlock routes you to getTargetBlockExact
thanks
Is there any guides on how to do this? Or am I on my own for stuff like this? I mainly just want a separate world with a custom sky color for a build.
pretty much on your own, though there are some plugins out there that do this kind of thing already
I don't know of any guides for packets. There's protocollib and packetevents, but it's simplest to work directly with net.minecraft.server code if you are targeting just one server version
I do wonder how it works now that it is all environmental attributes
how do i make items not stack
Pretty sure that varying metadata in any way makes it not stack
Like a library plugin?
oh okay
I'll try the nms version.
@edgy plank i think i have discovered the root issue, this was an absolute mammoth to navigate and debug.
I was just testing what I thought was the issue too
I was thinking it was the change in paper 1.21.4 #105
im finding it to be something a little different
what did you end up finding
it has to do with the client sending the DECLARE_COMMANDS packet, which I initially investigated through the TAB_COMPLETE packet.
i'm going to have AI summarise my findings and share them in just a sec
okay so @edgy plank i should preface this by saying:
on 1.21.4, if i do /tp {completions show up here}, i get the spoofed completions.
if i do /scoreboard players set {completions show up here} then i get the REAL player names. I thought this was extremely weird.
There are no differences between the ClientSuggestionProvider across the versions. they're basically the same
AI wrote this for me, but it encapsulates what i found
investigation.md by @midnight carbon: https://pastes.dev/V5XXRjWboi
so, I skimmed through this however I think what you saw is just a symptom of what I just described, though I am experiencing something weird here
let me share what I found
interesting...! what did you find
I made this little test plugin https://github.com/JavierFlores09/profile-testing
if you run ./gradlew runPreFix --console=plain you'll see that /tp (tab) shows both your profile name as it is on the server, and your profile name as it is on the client side (just the first 4 characters). However when running ./gradlew runPostFix --console=plain you'll see that only your client-side name is shown in the completions for /tp
the change in #105 was this: https://github.com/PaperMC/Paper/commit/5e23d28ad280b2955002a159b4f4235e2f326184. What that patch did was basically force commands to ask the server for suggestions all the time
i see. the patch sounds inconsistent with my findings though.
What that patch did was basically force commands to ask the server for suggestions all the time
if that is indeed the case, then ClientboundCommandSuggestionsPacket <—> ServerboundCommandSuggestionPacket pairs should always fire when typing /tp, but that isn't the behaviour i observed. on 1.20.4, the client would always ask the server for suggestions. but on 1.21.4, the client would not. at least not for the /tp command
i hope i am understanding this correctly, because it seems contradictory
Bukkit.getOnlinePlayers().size();
Bukkit.getMaxPlayers();
Is it safe to receive from an asynchronous thread?
I am not too sure, but as you can see in this video, the change in 105 is definitely what causes it @midnight carbon
in the first part, running in 105, you can see that only Memb is shown in /tp and /stopsound, but in 104 (pre-fix), both Memb and Membrillo are shown in /tp, and in the other commands only Membrillo is shown
why does tp end up with both the client-side and the server-side name I don't exactly know
so in short, the fact that server-side names were shown in suggestions was a side-effect of that patch, after it was removed the vanilla behavior was restored which is to only show the client-side names
sorry I accidentally replied to your message with the wrong thing lol. What do you need to call this in an asynchronous context for?
To write to the database. I want to take these values also from the async thread
why would you write something like that to a database if I may ask
but to answer the question, it is technically fine
not actually safe but chances of you deadlocking your server due to it are little, at most you'll get stale data when reading it
Thanks! By the way, does this apply to reading any kind of data? You can't modify the data, but can you read blocks, coordinates, etc., from the async thread?
nope
in this specific case, the server will not yell at you for it, in other instances you might be caught by the async catcher and the server will print a very huge red warning in your console
or in other instances you might just deadlock the server when reading just in the right conditions to hold some lock indefinitely
To submit this information to the website
Thanks for your reply!
you could just ping your server for that
if you have querying enabled that is
gives you a lot of info if you haven't heavily modified the server ping response
I'll think about it
Anybody have any creative ideas on how I could replicate this behaviour? https://www.youtube.com/watch?v=Cgc3iLGcR1U
I'm working on a project that needs vertical movement but the default vines and ladders are way too slow. My first thought was to check if the player was inside a twisting vine block and increase player speed in onPlayerMoved() but this turned out to be super glitchy.
I would try negative gravity
attributes are synced with the client, so that should be pretty smooth
that option should be disabled by default
is there any way with plugins/texturepacks to go back to the old obsfucation text effect, the new 1 looks bad
where in the protocol is https://minecraft.wiki/w/Java_Edition_protocol/Packets#Resolvable_Profile used, I can't find a single packet containing it
part of e.g. the object component or item components for skulls
object component?
Object text component that can render player heads
Beyond that, think entity data for mannequins
oh like in chat?
Ye
looks bad in what way
aren't they are the same except they support unicodes now
its just so think now
thin*
its got so much noise in it it just looks pixilated
the old 1 used to just cycle through characters really fast and looked way better
should be hardcoded in client code
hey guys why do my recipes not work after a /reload? while i dont intend to support reloading but i do wanna know why that happens, i even tried removing and readding the recipe
any way to make it so text displays stay static and dont change position based on the way the player looks at it?
set the billboard to fixed
thanks
wait
i dont want it fully static
i just dont want it to look 1 block ahead if the player looks up
if i spawn somewthing in there body
i have no idea what you mean tbh
ill record a gyazo
i want the same mechanic as a regular name plate
then use a different fixed billboard try both verticle and horizontal
i think vertical would fix it
alr thanks
i give up, if someone has code to make text displays function like regular name plates id appreciate if they could send it
I mean you can't see your own name tag to begin with
just ride them on player idk what do you want
What's the best way to update plugins without requiring a server restart?
If you were to make it possible on plugin level (no disabling and enabling random plugins, but building a plugin that supports that)
For example plugman seems to work fine, but it has some issues with brigadier commands and paper plugins
you don't
im on abt armorstand holograms
they are already passengers
The level that plugman gets to is presumably the best you can really get. I mean you could hack some more but
a lot of the server is not made for reloading / changing things
k ig I'll just need to deal w kicking all players when I want to make small changes
and prefer config options when possible
what are you even using, armorstand or text display
Yea I mean, if you have mini game servers you'd just slowly update things when they inevitably shutdown after a game
if you only run one server, create some lobby server, plug behind velocity and move them there for a bit
Could also spin up the "new version" of your server on a different port and move them there if e.g. your map and player data is static / storable in DB
textdisplay
i want it to be like an armorstand 1 but with a text display since i can use passengers and transforms to make it stay perfectly in sync with a player
Hello, I would like to know how to connect two plugins together. I can’t find any documentation about this
I'm curious about https://jd.papermc.io/paper/26.1.2/org/bukkit/event/inventory/HopperInventorySearchEvent.html
declaration: package: org.bukkit.event.inventory, class: HopperInventorySearchEvent
is there a reason why there's Block instead of Hopper tile passed there?
when available
what's your nametag looks like now
General uh when passing block states to events is that they are very very mutable
since there's no cheap way to get Tile / Block entity from block... but when HopperInventorySearchEvent is fired Tile / BlockEntity lookup was already done?
I mean, Block#getState(false) is probably cheap enough?
unless you want to implement custom hopper ticking and override hoppers on whole server and starting point is HopperInventorySearchEvent
thanks bro
And getState(false) is too expensive there?
That should do basically no copying of anything
The only thing you'll pay for is the BlockPos -> BlockEntity lookup
yep
which I'm already trying to bypass directly with paperweight plugin
.getBlockEntity(craftBlock.getPosition(), BlockEntityType.HOPPER)
.orElse(null);```
public static HopperView getHopperView(Block block) {
CraftBlock craftBlock = (CraftBlock) block;
if(!craftBlock.getBlockState().is(Blocks.HOPPER)) {
return null;
}
HopperBlockEntity hopperBlockEntity = craftBlock.getLevel()
.getBlockEntity(craftBlock.getPosition(), BlockEntityType.HOPPER)
.orElse(null);
return hopperBlockEntity != null ? new HopperView(hopperBlockEntity) : null;
}```
but even that could be skipped
if only we had Hopper in HopperInventorySearchEvent
Yea but we cannot expose that
Like, plugin A goes ahead and modifies the state in the event and then plugin B reads something completely wrong
yea I guess that's a valid point 😕
Its been painful already with ItemStack and we has been moving to defensive copying most of ItemStacks everywhere
What you could check
nah, that is the wrong container 😭
yep
Yea idk, once we get our event to interface work done we might be able to like
well with current impl that's probably unfixable, aside from using it to cancel stuff IMIE is probably not that useful/reliable
Do some funny shenanigans if keeping that reference on the event and then paperweight userdev allows people to fast access it
that would be awesome
tho, that opens a whole new can of worm around "yea so, why does this one event prevent GC from collecting half these chunks, oh there is an invisible block entity yay"
or maybe there's another way
eh no, I'm using Container from Hopper etc
was thinking possibly just adding set cooldown not just cancelling for HopperInventorySearchEvent would work
ie allowing plugins to set custom cooldowns for hoppers in HopperInventorySearchEvent
What's an easy way to detect if my plugin is being reloaded by plugman or /reload?
check if its disabled and enabled again with onEnable/onDisable?
you can check Server#isStopping in onDisable
Is making oversized item stacks (for example diamond sword with quantity of 2) unsafe? Just curious because I'm making an ability system where item size indicates remaining uses
Use item PDC
save yourself dupes, bugs, bypasses and painful migration once u understand PDC is the way
don't ask me how i know 🥹
I mean, I use that to display remaining uses to the user, actual system uses a map for that
like on inventory gui?
should work in theory if ur only concerned about paper compatibility and don't care about updates wiping data like they did for example with lvl 0 enchants
now if ur also using via, idk how that's handled there, if your using any plugins that "validate" itemstacks randomly here and there or relay on that data and assume harded max values... again same issue
there's probably some legacy code here and there related to this as in the past negative or overstacked itemstacks resulted in dupes
long time ago (i think? lol, we still wipe them 🤣 )
I mean, is it oversized if you just adjust the max stack size
it is a component nowadays so you could just make swords stackable if you wanted
It works, I just wanted to know if there are any unexpected things thay could happen because of that, thanks
Omg, I didn't know about that, thanks
with the text display?
if so its fine just if you look up or down it appears way ahead of you and idk how to fix that
Does location#setBlock work on blocks in unloaded chunks? And if so, does it load the chunk async or sync?
unlike with armorstands it will just tilt up etc
vanilla nametag is the same
if this is text display, then it's working just the same with nametag
wouldn't that be location#getBlock then set? if so getBlock loads...
there is no Location#setBlock yeah ^, are you thinking of World::setBlockData?
that methods does load the chunk synchronously iirc, let me check
i mean it kinda has to
yeah I was just checking if it just failed in unloaded chunks, though I guess that would make it annoying to use lol
Is is possible to unregister commands?
yesn't
when using lifecycle manager*
it is possible but the API doesn't have a nice method to do it, so you have to manually mess with the brig dispatcher for it
I think it'd be easier to set a permission/predicate (whatever it's called) that you just ensure fails for everyone when you want it 'disabled'.
proper way to "remove" commands would be to just permission-gate them yeah
yeah seems like the best way
just remember to do Player#updateCommands or whatever the method was in order for the command tree to be resent when you change permissions
so ig something like this should work?
public static boolean enabled = false;
// ...
.requires((_) -> enabled)
yeah but if I want to completely disable the whole command if the module is disabled from config
for everyone
I mean, there's nothing wrong with that however I don't think it is necessary to do it via a config when the usual way server admins add/remove commands to players is via permissions
if you want to do it that way however, it is fine
Yeah I did mean getBlock then set my bad
Thanks
Yeah that would be the normal way, but as I want to make the plugin modular (it will have 5+ modules), and I want all of them to be disabled / enabled from config on need so that not everything is always enabled.
including commands and listeners etc
how do you handle registering commands past the lifecycle event
do you just Server/Bukkit#reloadData?
because in that case, you could simply not register them based on what the config is
no I alr do that
but if for some reason the user wants to disable a module while server is running
in that case you should just do a Server#reloadData
that will trigger the lifecycle event again
of course, it may lag the server given it also reloads advancements and recipes
Just tell them no
What would be the advantage of doing Server#reloadData()?
that it'd trigger the necessary lifecycle hooks again
over just making a bogus permission check with config coded boolean
wouldn't that require the plugin to remove the command from the lifecycle manager anyway
If you leave the commands and event handlers registered and just if (disabled) return that's less awful
or is the permission check not dynamic
Trying to dynamically register/unregister that stuff is where you get headaches
this is what I have rn
and just toggle it around when needed
Of course that'd leave the command visible to users, at least until they rejoin
to be frank, there's nothing wrong with this approach (or at least I can't think of any downsides off the top of my head), it just feels like it'll be annoying in some way or another
what if I do Main.instance.getServer().getOnlinePlayers().forEach(Player::updateCommands);
that should work fine
I mean the logical issue is that what if some plugin want's to use that command space for something else, but that's an edge case that should never happen
that could be a thing but given commands are namespaced, it'll just be annoying at best yeah
even then, one would usually just remove plugins which share commands like that
Can I replace sendMessage with sendRichMessage and work without replacing anything (legacy working too)
§don't work in that
Will & work
|| no ||
Still better than no minimessage and too bored to parse it so ill take it
Yea I mean, there should be no method in our API that can work with legacy (§ or &) that isn't deprecated
If I have literally 100 plugins using SQLite (not the same file, one for each plugin), and I also have optimized requests, only read/write on entry/exit, should i change to a remote database?
I don't think it should really have a big impact
if you wrote good non blocking code you are not going to feel any difference
It's better a local independent database, but not by a lot. What would actually be beneficial is merging the database accessed into 1 plugin that does it and others using the data from it, but that's if thise are private plugins
How do I get/set the actual chat format in an AsyncChatEvent instead of just the message part.
You need to set a custom implementation https://jd.papermc.io/paper/26.1.2/io/papermc/paper/event/player/AbstractChatEvent.html#renderer(io.papermc.paper.chat.ChatRenderer)
🤔
Yeah all of them just read/write async
maybe even has slightly worse performance on an external database as you get networking latency.
if everything is async, like you already said, probably wont have a noticable difference.
I personally like to use SQLite for my plugins as i think setting up a proper database server is only worth the effort if the database actually needs to be shared between different servers.
(Maybe its a bit different if your server is very very large though, i only know working on smaller servers)
Yeah idk we are having some lag issues somewhere
The sparks just shows some plugins lagging randomly
if everything is truely async, then that probably does not come from the database and changing it wont make a difference
Yes, I thought it was some plugin from the previous developer they asked me to redo them
good thing spark can show you the exact method which consumes the most tick time so you can figure out what the server is hanging on.
There's a more complex example here: https://docs.papermc.io/paper/dev/component-api/signed-messages/#example-making-user-sent-messages-deletable
Obviously that's part of the signed messages docs, but it showcases more complex formatting logic as well
hi i'm new to plugin dev, i just made a cool plugin in 26.1.2
but i wanted to know whether I can make it work on all versions from 1.21 to 26.1.2
i dont exactly know what to do here
to check whether my plugin is compatible with 1.21+
It's weird because in each Spark we do, the plugin that consumes the most is different
Set the API version on your paper-plugin.yml to 1.21. If you do this, you cannot use methods that were added in 26.1.2 you must use methods that are available from the version you want to support
and are you sure its not just a simple case of the hardware being too slow?
the plugin.yml in resources?
i dont see a paper-plugin.yml
https://minidigger.github.io/api-diff/since.html
You can use that to see if you are using a method that doesnt exist on older versions, anyway setting the api version to 1.21 and testing will show you errors if there are
oooh
Yeah plugin.yml assumint you are using bukkit way
It's like every 2 hours or so the server lags out of nowhere and causes errors in plugins that use SQLite databases we don't understand why
these
Not really
oh there are actual errors?
ig share them
Yeah all of my sql plugins just throw database busy
Not all of them are mine, but that still happens
that does sound like a simple case of the hardware being too slow
We're not sure, we're looking into it, because it's very weird
please share a spark report
I already remade like 10 plugins to optimize the server
there is no point in focusing performance if you get errors
I'll ask if I can show some
why wouldnt you be able to share one?
its not like they contain critical information
I know, but I'll ask anyway out of courtesy it's not my server anyway
alright
@true flint also i think we should move this topic to #paper-help, this doesnt seem like a plugin programming issue.
Maybe, i'm replacing the plugins from the old dev
They were really trash
i'm getting errors when I runServer to test it on 1.21.1
i cant figure out why
can you help me? i'll send the logs
Just send them
107 lines
I did delete the run folder, I left out ops.json and eula.txt cause i keep having to op myself and accept eula again after a clean test
should i try again with a fully clean test this time?
I created my project like this, if this helps
I'm sorry i'm just new to this
Not really
Newer saw those errors tho
Maybe is because of something new about the templates plugin
i'm pretty sure it's something to do with the build.gradle.kts file?
Sent it
Why are you running Paper for 1.21
He wants to test if his plugin can support those versions
Well, the problem is that the remapper does not support Java 25
here's both probably relevant files
build.gradle.kts by @fierce elm: https://pastes.dev/2jUFma23Xw
plugin.yml by @fierce elm: https://pastes.dev/WvCdOErclJ
That means his plugin will definitely not run on Paper 1.21
in the plugin world, you usually just support the newest version.
its not like in the mod world where people are expected to stick to older versions.
its very much a big issue to run outdated servers
If you want your plugin to run on 1.21, compile it against 1.21
Remmaper is something new on 26?
Remapper doesn't even exist on 26.1, but the thing is that the Paper remapper in 1.21 does not have the required dependency to support Java 25 classes
ahhh I see
what if someone has an older paper server who wants to use my plugins because some of their plugins haven't been updated?
I don't even think 1.21.10 supports Java 25 classes. 1.21.11 has updated dependencies though to support it
then they need to search for replacements of these outdated plugins
I see
old versions contain big security problems
and even stuff like 1.21 is considered "old"
They should not be running an older Paper server in the first place. We don't support anything below 1.21.11 anyways
It did support them, idk about anything lower than 1.21.10
Just do yourself a favor and build your plugin for 26.1.2
What is the remapper for? I mean what it does
wdym
there is literally no point in running 26.1 these days as 26.1.2 is protocol compatible with 26.1 clients anyways
26.1 paper mever released
26.1.1 only had some client side method implementation difference with 26.1.2 and it existed for only like a week
i see so i'll just stick with 26.1.2 then
when developign for paper, you always target the newest paper version
Well, if you depend on 26.1.1 API, you will not have any API changes that were introduces in 26.1.2. They aren't backported after all
gotcha
You can just use 26.1.2 and say you support 26.1.x, nobody will use those versions
26.1 and 26.1.1 basically didn't exist
thanks so much for lmk 😭
The remapper was used to convert plugins using Spigot mappings (an only-half-deobfuscated mess) to nice and readable Mojang mappings
It was dropped in 26.1
I think I'm the only person who makes all his plugins (more than 100) for the 1.21.1 base and expects them to work in newer versions 
Probably not the only one, but a minority for sure
Oh ok thank you
does anyone have a gitignore template 😅
If you're careful about what features you use (and what newer MC functionality you care about) you can make a plugin work across many versions
that i can use
Something like ```
.gradle
build
run
Is generally already sufficient for most cases
If you want to use the latest APIs, the latest MC features, or dig into MC internals you either support a single MC version or you bring yourself a world of pain
Latest meaning anything created after about 2016 😄
Doesnt look useful for a minecraft plugin github repo
alright
Didn't the MC dev plugin generate a .gitignore for you? Or did you not tick the git repo button?
yeah i wasn't aware of the context mb
i did not tick the git repo
its ok
i didnt think at the time of creating that i'd make this into a plugin i'd publish lol
tysm
is there any formatter in java? do people use it usually?
for example, there's black formatter in python,
you can run the cli or use an extension to automatically format your code into PEP 8 standards
a lot of people use it
IntelliJ has a built-in formatter
oh? i dont have it enabled
You can use it via CTRL + ALT + L
You definitely have it enabled, it's just behind a keybind
If you want your files to be formatted automatically, you can configure that
It's also endlessly customizable
ooo
it only changed 1 line
do i write my code that well as a beginner 😭
You can configure auto format under Tools > Actions on Save
iirc it also defaults to keeping a lot of whitespace
By default, the formatter doesn't completely de-nuke your code, much different to something like rust's rustfmt, which will force its ideals onto your code file
So if you format things in a weird way it'll try to not blow away what you did assuming it was an intentional exception
It does get rid of the obvious misplaced whitespace stuff though
If you put those all on separate lines it'd keep that though
But it keeps the general stuff the same
i see
I honestly very much like it like that, since I can decide myself how stuff should look in code, whilst still having stuff formatted nicely
is there a way to force cancel the consuming animation?
since I come from python I usually let the formatter take control of how it wants to format the code lol so this seemed strange
Well, you have much more control over the format now!
mhm
If you check out Editor > Code Style > Java in the settings screen, there are a ton of options you can set for the formatter
Though I would just recommend keeping it as it is and basically write code yourself in a way that you think looks natural and good
Java devs are not super strict when it comes to code formatting
what do all of those do?
I would recommend the optimize imports one, otherwise keep stuff disabled
Optimize imports for example removes unused imports (greyed out, not used in code)
ooooh
Rearrange code physically moves around your methods and fields. You can enable that one I guess, though it will mess with your method order, which can be disorienting
