#help-development
1 messages · Page 412 of 1
I see, thank you
Now it's time to look over the internet how to create a clientside entity in 1.19.3 🫡
ProtocolLib or NMS
Nms
Ouch
in git bash, do ./gradlew build
good luck lmfao
bruh git bash
Is protocollib better approachable hmmm?
i dont even have that crap
definitely not
It is because the final character is delete which is not a printable one\
It's not that hard
protocollib is so much more complicated
More version resistant
NMS packets are easy
I don't like protocol
Ah but I only use 1 version
but, on the other hand it's easier to maintain lol
the opposite is true imho
ah then NMS is fine
hm?
ProtocolLib be like getIntegers().set(2, someThing)
it'll always compile
then fail on runtime
with NMS you can see whether it compiles and what fields you need etc
change in NMS = you instantly see what has changed.
in protocollib, you'll just get an error on runtime
Simple command time map BABYYYYYYYYYY
Okay ill give it a try through NMS
Do any of you happen to have a good source where I can learn how to create an entity clientside only in 1.19.3?
Only if they register the commands properly
yeah it's good for listeners, but sending packets is definitely easier in NMS imho
fr
nvm
I am dum
you better be kiddin' me
Use /
./gradlew
ahh cmon man
SimpleCommandMap commandMap = ((CraftServer) Bukkit.getServer()).getCommandMap();
Stream<PluginCommand> myPluginsCommands = commandMap.getCommands().stream()
.filter(command -> command instanceof PluginCommand)
.map(command -> (PluginCommand) command)
.filter(command -> command.getPlugin().equals(myPlugin));
Can anyone take a look at #1084938453730459770, it seems as if the angle between the vectors does not change even with the new location
Alex
what
redownloading it? i just downloaded gradle?
gradlew is inside the repo
so
He only needs the command names, as he's filtering in the command message
Yeah because it's NMS
You don't need it for what you're doing
spoonfeed me please 🥹
that snippet is not what you need though
well someone told me to download gradle and add it to my path 💀
yeah it's craftbukkit
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
for(Map<String, Map<String, Object>> commands : plugin.getDescription().getCommands()) {
for(String name : commands.keySet()) {
PluginCommand command = plugin.getCommand(name);
// Do your thing with the command
}
}
}
``` @last temple @tender shard
you can do it version-independent with reflection:
Class<?> craftServerClass = Bukkit.getServer().getClass();
Method getSimpleCommandMapMethod = craftServerClass.getMethod("getCommandMap");
SimpleCommandMap commandMap = getSimpleCommandMapMethod.invoke(Bukkit.getServer());
alex the spigot api literally has it built in
that only works for commands registered through plugin.yml
Of course, it's his plugin
what does it have builtin?
morice do you need dynamically generated commands as well
getting plugin.yml commands
I don't think he wants dyn commands
ah, then go with alex's
why would one loop over their own plugin.yml
this gets you the simple command map in EVERY version. no need for any craftbukkit imports
Also I am wondering why the fuck does the angle between two locations not change if I change their pos
like what the hell
I am bad at maths in general
you should really cache the commands FYI
you should rethrow the exception, so you get a proper stacktrace in case it goes wrong
already hating it
just warp it into a RuntimeException in the catch block
Yeah, for each player relog or perm update it will loop over every registered command (and it's aliases)
Gradle likes to run in the background. Kill it with task manager
now only find it
I usually just kill every Java program running but you could start by killing the one with lowest cpu usage
Spigot do be having opinionated maths fr
WMIC PROCESS where "Name like 'java%' AND CommandLine like '%GradleDaemon%'" Call Terminate did the job
Where do you learn this? I couldn’t find much specific information online about NMS, only about what it is
A ton of experience
just kill all gradles with bash ```sh
ps aux | grep gradle | awk '{print $2}' | kill -9
I have to repeat, that's not NMS
windows
no git bash?
I was about to say the same thing
making plugins huh
I’m working as a developer at DDG
Huh?
hmm I think I am forgetting to add some dependency to make my NMS imports work? What could it be?
As only a few imports seem to work from net.minecraft (1.19.3)
https://gyazo.com/a4d922a02a8f783286bf302ed088500f
anyway, for NMS: You gotta decompile the classes yourself, then look into them. There's not much information or tutorials about NMS, and if there are, they are all outdated
seems like you're not using mojang maps
are you using maven?
if so:
?nms
I expected that, but I still had some hope there was information out there. Ah well, thanks I guess
Not really D:
Does minestom exit with non-0 return code?
no
Run your commandmap stuff one tick later
Oh wait you do it in a listener already?
Forget what i said
still this bruh
The extra slash is worldedit
//brush is /brush in the map
are you sure your filter() things are correct?
print out your commandsToRemove thing
I don't think so, but just try it
the / is part of the command, WE/WG have extra aliases like //br
Still don't understand the why
tyty, fixed it 👍
np
1+1=2
Spigot would interpret that as 1+1=-456.4
lul
Listen on lowest, maybe the other plugins use the preprocessevent to do their stuff :X
- 4634254⁷⁹ / 9
Does anyone know how to make eclipse not insert @NotNull or @Nullable twice when creating method stubs?
And with that I don't mean switching to annotations-java5, I'd like to stay with the recent one
LMAO

Then get another ide
Well then, time to figure out how to compile eclipse from source
Whats the problem with java 5 annitations?
I will commit fell out of the world
thats a later question
whats the problem with intellij
Using them also fixes the javadocs bug
You can't use it on types iirc. Whatever the cause there was something funny going on
You can
goddamn gradle
gradle is love
why cant it just work straight from the beginning
I believe you cannot - only on methods, fields and variables
prev time i cloned this project it worked just fine
So you cannot have generics annotated with @NotNull or @Nullable
but once you have TYPE_USE and METHOD/FIELD you have the bug occuring
where / how does it create double annotations?
can you show an example
all I can say is that lombok's annotations are great and they also don't have the javadoc bug that jetbrains annotations have
Do you happen to have a code snippet of spawning an entity clientside only somewhere? I am a bit overwhelmed by the amount of options 🫠
Lombok probably doesn't support METHOD and FIELD - which is the only proper way of doing it
Could very well be that IJ doesn't have this bug
It really isn't that hard to fix once you find the source.
Should just be a weekend project
-
create a new NMS entity
(E.g. new ArmorStand(world, x, y, z); -
send a ClientboundAddEntityPacket to the player
1.19 packet naming conventions 👎
I see. That'll do I was actually fairly close then 🫡
1.19? They've been called like that forever
Tyty
PacketPlayOutEntitySpawn days
oh yeah i forgot i always just used spigot mappings
still the better naming conventions
I don't think so
What would be the difference between that and ClientboundSetEntityDataPacket?
you usually send both
first you spawn it, then the meta data
that's how I make "fake entities" visible to a player
the "Object entity" is an NMS entity
PacketUtils is trivial
I see :)
Do you happen to know if a player is able to hit through their clientside entity? As in does it hit a player behind the clientside entity if it's in the way?
I don't know that
probably not
since the client itself sends "I clicked on entity with id 123" to the server
Fair fair 🤔 I guess I'll find a workaround for that
what do i need to know then it comes to thread and running multiple instance of the minigame on thread?
talking about java + spigot ofc
would the propper way be to start more threads?
If the threads are short-lived: don't.
yeah it is term run for the game itself
any reason you want each instance to be on seperate thread ?
idk I'm just asking consider your question i might consider to make it appear to be on thread
the error is because the beam isnt getting targeted though ( @quaint mantle )
the direct cause of the problem is the runnable im asuming
the input is the squid which definetly exists
You should optimize your minigame if it runs so poorly that each instance must run in its own thread
this.scheduler = Bukkit.getScheduler().scheduleSyncRepeatingTask(SuperShows.getInstance(), () -> guardian.setTarget(squid), 0L, 1L);
Uh you should possibly rather just cancel https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/entity/EntityTargetEvent.html
declaration: package: org.bukkit.event.entity, class: EntityTargetEvent
ill just send my original problem incase anyone else knows
at nesancodev.com.supershows.lasers.Laser.target(Laser.java:71) ~[SuperShows-1.0-SNAPSHOT.jar:?]
at nesancodev.com.supershows.lasers.LaserCommand.onCommand(LaserCommand.java:25) ~[SuperShows-1.0-SNAPSHOT.jar:?]
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[pufferfish-api-1.19.3-R0.1-SNAPSHOT.jar:?]
... 23 more```
why is getTarget returning null?
public Laser(String name) {
this.name = name;
}
public void create(Location location) {
this.location = location;
this.guardianStand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
this.squidStand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
this.guardian = (ElderGuardian) location.getWorld().spawnEntity(location, EntityType.ELDER_GUARDIAN);
this.squid = (Squid) location.getWorld().spawnEntity(location, EntityType.SQUID);
this.scheduler = Bukkit.getScheduler().scheduleSyncRepeatingTask(SuperShows.getInstance(), () -> guardian.setTarget(squid), 0L, 1L);
guardianStand.setInvisible(true);
guardianStand.setGravity(false);
guardianStand.setInvulnerable(true);
guardianStand.setCollidable(false);
squidStand.setInvisible(true);
squidStand.setGravity(false);
squidStand.setInvulnerable(true);
squidStand.setCollidable(false);
guardian.setInvisible(true);
guardian.setGravity(false);
guardian.setInvulnerable(true);
guardian.setCollidable(false);
guardian.setLaser(true);
squid.setInvisible(true);
squid.setGravity(false);
squid.setCollidable(false);
squid.setInvulnerable(true);
guardianStand.addPassenger(guardian);
squidStand.addPassenger(squid);
}```
You left the important line out
huh?
Error is talking about Laser#target and you are instead showing Laser#create
the only relevent thing from the target method is Location baseLocation = guardian.getTarget().getLocation(); which is where the error is from
?paste
need to see the code so people can help with the code
ive tried all the ways posibles and just i wanna do it
just the easiest and non complex way
naming conventions 😭
and im hurried up bc my friend needs it for the next week
e.getWhoClicked().sendMessage("PENEEENENEN"); is this line running
everything its executing but not the p.openInventory(inventory2)
@tender shard Tried to reproduce the null annotations issue with the 2023-03 release candidate and it seems fixed. Let's hope that stays like that until tomorrow when eclipse 2023-03 is released for good
Which annotation issue?
Did Eclipse fix the duplicate annotation issue in the jdk?
I fucking hope so >:((
how would I check if an itemstack is a door for example instead of checking every single type of door
nvm I asked chatgpt
chatgpt replaces spigot help lol
public boolean isTrapdoor(ItemStack itemStack) {
Material material = itemStack.getType();
if (material.isBlock()) {
BlockData blockData = Bukkit.createBlockData(material);
return blockData instanceof Trapdoor;
}
return false;
}```
do u think this would work tho
idk
are you trying to make a check?
yea
cuz there is different types of trapdoors
so im not tryna make 1000 if statements
can anyone help me edit a plugin to only happen when shifting
Without saying what the plugin is, providing a link to it etc.. It's a bit hard for anyone to help.
Does it have a github repo link?
If it isnt open source then most here are probably not going to touch it
First because it is a pain to decompile and then recompile and second its closed source
Looks closed source to me. Would be easier to just pay someone to make a copy of it lol. Not a lot going on reading the desc
I was working on an auto smelt tool and while it works it doesnt turn logs into charcoal which I want it to do. I am looping through FurnaceRecipe's any reason why that wouldnt count?
We’d need to see some code
public void cookDrops(UUID uuid){
List<ItemStack> items = blockDrops.get(uuid);
Iterator<Recipe> iter = Bukkit.recipeIterator();
for(ItemStack i: items){
Bukkit.getPlayer(uuid).sendMessage(String.valueOf(i.getType()));
while (iter.hasNext()) {
Recipe recipe = iter.next();
if (!(recipe instanceof FurnaceRecipe)) continue;
if (((FurnaceRecipe) recipe).getInput().getType() != i.getType()) continue;
ItemStack result = recipe.getResult();
result.setAmount(i.getAmount());
items.add(result);
items.remove(i);
}
}
}
Everything smelts that can except for logs or thats at least the only one I noticed
Why do all my NMS entities disappear when I die and hit respawn?
Probably despawning?
I can teleport far away and they work fine
Plus I still hear them walking towards me on the grass
Teleporting is different from respawning
Well they should stay since I have their Entity.persistent = true
And they do
I hear their footsteps
Just no visuals
Try CookingRecipe
The armor stands (holograms, separate) are not being sent
Two different areas of code. Respawning the server already knows you are not around. Teleporting not so much the case because unlike respawning teleporting isnt part of the ticking for everything else
I'm thinking about making an NMS entity tracker for this btw
Where would I get started
Where should I look
It’s hard to answer a programming question without code
Oh no! You ran into a problem. But no worries, people are willing to help, but first they need to see your code. This is because otherwise, they would be providing help based on guesses instead of concrete knowledge. Whether it be a compile error, runtime error, or an unexpected output, I'm sure that if you were to provide code, you'd receive a quick solution.
Also since you are messing with nms, which not sure why. It can sometimes bypass things
No that breaks the ores and still doesnt work with logs
Wdym it can bypass things
Nms isnt designed to be messed with. Therefore there isnt inherent checks to see what you are or are not doing. If you spawn an entity via nms and lets say its not a real entity but done via packets. Then the server isnt going to know about it or track it. Also depending on what code you are touching you dont have the protections of the api or in some cases tracking
Ye of course
The client unloads everything when you respawn
I understand that
Thank you
Are there any articles or anything about writing my own entity tracker?
But as i also said respawning and teleporting touch two different areas of code
That code is what I’ve used in the paste
Worked fine in 1.18
I just want to warn you this is not an easy task. I'd rather start with the question whether you really need to do it with NMS and whether there are any benefits at doing it
The benefits for using NMS for me is I can have a fake entity displayed to the user that my invisible, server-only entity can send to clients. Only one set of pathfinding code has to be written and I don't have to extend a bunch of entity classes for each entity type
Also I have holograms
Per-player holograms will also be a facet
Holograms dont inherently require nms
No, but per-player holograms do
Not even
And they are also more efficient when only done with NMS
Ig. you could intercept packet and cancel it to certain players
But i'm going the nms route for those reasons
Alright. Atleast we know now
When I print out all of the recipe types its looking for the only log is Dark Oak and that one works
Ill try this out
Yeah the charcoal recipe is a single recipe with multiple possible ingredients
That I'm aware of but are there any resources on what creating an entity tracker entails?
Hence why my code handles MaterialChoice
public interface NetworkEntity {
void addViewer(Player player);
void removeViewer(Player player);
Location getPosition();
}```
I want to have an interface like that
Where viewers can be added and removed for the class
And the position is also returned
At a basic level its can be nothing more then a map. But how much more it needs to be is dependent on you and your requirements
Map of what to what
Chunk to Entity?
Should I iterate over all players on tick and give them nearby chunks of entities?
A map containing entities or objects that contain your entities. If you want to map to chunks you can either add that info to your entities or have a double map for that
And since these are fake entities you could also make the map thread safe too if you want to access it from other threads
But see how much more complex it can be? Lol what you need is dependent on your requirements that you identify and there is numerous ways to do this all with their own benefits and drawbacks
Yea it does seem complex
But at minimum you only need a list or map to hold your entities or objects so they dont disappaer
Then from there you make it accessible to the rest of your code
Which can cause you to change from list to say concurrenthashmap instead. But that isnt something we can determine for you
All we can do is just give you concepts and sudo code lol
Is it good practice to send packets from other threads or are they already queued up for you and sent asynch on 1.12.2?
Netty sends packets async however that doesnt mean you cant use a thread to send a packet through netty and you might want to if its only purpose is to do that because now that piece of code isnt running on the main thread
Interesting
I'm just trying to think of how I should determine when a client needs to be sent the entity again
The only thing to worry about with threads is concurrent modification exceptions. Some things like a list for example cant be modified and read from at the same time if the list lives on the main thread and you are trying to do things with it from another thread. So a way around this is to sometimes clone that list locally to the thread
Just depends what the list is and if its ok of the data in it is slightly outdated or of the data isnt expected to change right away
Will I be informed about a ConcurrentModificationException or will a race condition randomly break something without my knowledge?
If a cme happens it will be thrown in the cpnsole
Race condition is different and that can happen and harder to detect sometimes but that is what profilers are for
Another thing that can happen is deadlocking
Which is the opposite of race conditions
Two mutexes waiting on each other
Yep
Does Java have mutexes
Or waiting on the same resource that wont be freed
Mutexes yes but more for networking side. It is typically referred to contexts because you dont need two threads to deadlock you can deadlock a single thread on itself
So back on the entity tracker discussion (I know I'm sorry 😅 ) what happens if I send a spawn packet for an existing entity? Will the entity just be updated since the client should notice the existing entity id?
Got it thank you
USD$2 for a cup of coffee and youve got a deal.
Not entirely sure. This is something that isnt supposed to happen due to uuids. So on the client side, client could throw an error its in log and nothing else happens, or it just ignores it. It could causen it to update that one entity it knows about
So avoid it because it's UB
You should do your best to avoid it or you can just go ahead and find out what happens
Its one of those undertermined things lol
Lmao yea and since I'll be using a ViaVersion proxy for the network probably best to avoid any shit like that
Could vary between users
Indeed
Welp back to work for me. If these are things that interest you and you are wanting to explore the code and intrinsics more in depth. Recommend verifying and sticking around. Plenty of us who have knowledge to dispel. Not just me lol
Yessir thank you very much for giving up 30 minutes to teach me
Definitely appreciated
I am using the OnPlayerAnimation to run player.sendBlockDamage and the mining speed and everything is perfect but I get a weird few frames where the block breaking animation flickers any thought why that would be?
Its too much code to send if you really need to see it I can get a few pastebin files but essentials its onPlayerAnimation runs a function that gets an object from a map I made that updates the block progress(in the object) and every time the animation event is played it updates the block progress(in the game) to to number
It looks kinda like it's setting the frame back to default then the next one?
Like 1 > 0 > 2 > 0...
Since you are sending the block damage manually you need to cancel the block damage event
Otherwise you are just fighting the server
I gave the player haste -1 so I think think I should be sending damage unless I am just slowly
are you cancelling the original damage?
Not sure what potion effects have to do with the event
Yo, im having trouble understanding the new event.joinMessage() component, since event.setJoinMessage() is depreciated im not sure how to make custom join and leave messages now. Im using Kotlin. Any pointers? Checked the docs and it was no help.
Also not even sure if mining fatigue stops the event in spigot
wrong discord
mb, didnt know they had help channels
should be paper-dev
no but it doesnt cycle the animation iirc
Even if they didnt this is still spigot. Not help for whatever fork you are using
I canceled the block damage event still happening
paper
they deprecate all string bukkit stuff and make people use minimessage components
i said mb
Only thing then that i can think then is that your object isnt updating like you think it is
That is on two iterations the object is the same thus same packet being sent twice
If this is something being done async with the reading and updating of the object i would probably toss the synchronized keyword on map or list holding your object to see if that is the case. Synchronized makes it impossible for two things to being doing something with it
Seems it would be easier if you were using block damage event
Because you can more easily control the damage to it without resorting to some manual method
kyoris adventure components
Component.text("stuff") iirc
Well the block damage event only fires when you first hit the block it doesn't continue as you are mining it so I would have to automate the mining then cancel it if the abort event was fired I figured it would just be better to have it based on the animation so I can control the speed a little better as they are mining.
Ah got it. Well i am work so not sure what is best then to ensure you are not sending duplicate data. Might have to look to see where that might be happening
?jd-s me
nice!
it's not deprecated
see
using paper, meaning it is deprecated
yeah in paper every string method is deprecated
https://github.com/PaperMC/Paper/blob/master/patches/api/0005-Adventure.patch
idk why they thought this was a good idea lol
no fuckin way they forked bungeecord chat just to put god damn Deprecation marks
fuckin semver
Well, Mojang removed legacy chat like half a decade ago, so it makes sense to notify devs of that and get them to move on to the way more powerful components
Yeah I'm happy with Strings for most things
The only use for components is clickable etc
Let them provide a string method that wraps it in a component then
But lemme guess Paper doesnt doo that
?jd
But components can't contain legacy, so that would be a breaking API change
theres a ChatEvent, that might be the best youll get
also wtf is the command to get specific docs
i know ?jd-s for spigot but
is it like
?jd-bc
?jd
?jd-bcc
aha
🙂
gotta start documenting the commands in spigot discord
There's some bot command to list them all. That's the real one you should remember. I wish I did
itn't that the ?cc one that only works in trivia?
sure, the chat colors are shitty, but sometimes you just want to use a normal string. What annoys me is that it's only deprecated in paper, but not spigot. So people here all the time say "but that's deprecated", and we have to send ?whereami again lol
I can't do anything about people asking in the wrong place, we have to deal with that too
I know lol
And for normal string (with no color), sendMessage (Component.text("string")) isn't that worse, especially with static imports, plus it's explicit
In my opinion Spigot is the API. No fork should make changes to the root, only additions.
that is my opinion too
additions, nice. changes to the original api however, not a good idea
Ok so we have to stuck with bad decision from upstream? Or unwillingness to innovate?
The methods aren't broken, just deprecated because there are better alternatives
innovate all you want, in your own methods. Changes to the Spigot API shoudl only be made by Spigot.
You can choose to ignore that, they aren't deprecated for removal
well nobody forces anyone to agree with elgar or me
No, devs can choose
Either depend on spigot or depend on our API
Just like server owners are choosing
We make sure stuff is backwards compatible with upstream, at least for now
Server owners are not choosing the API, they are choosing for performance.
In the future devs will have to make a choice, just like most server admins already made a choice
does anybody know the translation key names for builtin enchantments? can't find them in code rn
copilot suggested "enchantment.myplugin.enchantmentname" for me
lol
They are choosing the whole package of performance, exploit and bug fixes, config options and yes, API too, because that also makes a difference to performance in many case
not really, 99% of server owners don't even know what an API is
I disagree
all they know is "paper is faster" so they use paper
I.e. we allow you to get a block state without cloning it, or get a chunk without loading it sync, or teleporting without sync chunk loads
Yes, performance improvements, but the server owner knows nothign of whats behind the curtain
Not ever server owners knows that, but many plugin devs already state that their plugin makes use of such API if available and thus will on better on paper
So devs are educating server owners, like they should
I only write for Spigot so can;t comment on any forks "improvements"
uugh why does this not suppress the warning D:
oh i'm stupid
it's "deprecation" not "deprecated"
That's fine, maybe you will give them a chance one day, maybe you will stick to spigot till it dies, who knows, that's a choice you will have to make
Spigot all the way baby, I dislike the Paper community so When/If spigot dies I'm gone.
is there an intellij shortcut to jump to the currently open class?
I.e. I got ClassA open in the editor and I wanna have it selected in the Project folder
personally im a big fan of Spigot components 
said nobody ever
thats clean
as someone said a while while while ago, having to make them arrays just hurts inside a little
how would you create a message in spigot components like this?
<red>This is red text<gold><click link="https://somelink">Click Here to open whatever
e.g. only the golden part should be clickable / run a command / whatever
That's using MiniMessage isn't it?
Alt + F1 ---> Project View
the Download | Donate | Changelog thing
doesn't do anything for me
That's the worst thing, they aren't part of spigot so they are not used everywhere
Well, the other way is through the menu buttons. But that should be the shortcut. 😛
ah thx
hm idk why it's not Alt+F1 for me, I'm using the default keymap with only minor changes lol
new ComponentBuilder("This is red text")
.color(ChatColor.RED)
.append("Click here to open whatever")
.event(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://winnpixie.xyz/"))
.color(ChatColor.GOLD)
.create();``` if im not mistaken
hm thx I'll try this later
wdym not part of spigot?
yeah bungeecord components are definitely part of spigot api
yes, thru the kind of weird .spigot() method
I meant spigots fork of Bukkit
yeah never understood what that was for lol
I doesn't know why shit is still separated
It's confusing as heck
Anyways, whenever talking with Choco why spigot doesn't use components in more places, that's the response I get
maybe once Choco completely integrates Components, itll migrate to bukkit 
Is that before or after spigots fork of Bukkit updates to modern java versions?
what would be the advantage of using >8 for bukkit?
im with alex on that one, what benefit is it for the API to update?
Why hold back? Lol
i cant think of anything outstandingly obvious rn
so people can still compile for java 8 to create a plugin that works in 1.8 to 1.19
There are plenty of new language additions that are useful for apis, i.e. sealed classes
They wouldn't compile against a newer API?
and which class in bukkit would you like to make sealed?
Most of them, lol
I usually compile against the latest api even when supporting older versions
Every Bukkit class that shouldn't be extended by plugins
Which is the majority
was this @ my msg above
That's dum, how do you make sure to not use newer API then?
yep
o
thx
im probably the only person that will advocate for spigot components if ur usin spigot
xd
to date I have had no use of components
I've stopped supporting versions older than 1.13+ I'll always prioritize newer versions now. Because supporting anything older is too much work these days.
Well usually i know which api exists in 1.16 and which doesnt
I do 1.16.5+
tbh comparing this code to an adventure equivalent would be pretty much the same code
1.18+ xD
That seems like unnecessary cognitive load
Yeah, my next update will probably be for something like that, or 1.18+
When you can just let the compiler help you
theyre both builder-style, so probably why
Then how would i use 1.19 features though
Just that adventure mirrors vanilla more closely and builds proper tree like structures and not arrays
You can't on older versions?
Maybe you misunderstood what i meant, or i explained it badly
One sec
i would honestly have to look @ stash to see why in gods name it returns an array
And you can still compile with target 8 even if you use libs that target newer stuff Alex
At least am pretty sure you can
/**
* Gets the lowest possible building height for a world. It's the same as {@link World#getMinHeight()} but also works on 1.16.4 and earlier
*/
public static int getWorldMinHeight(final @Nonnull World world) {
return HAS_WORLD_MIN_HEIGHT_METHOD ? world.getMinHeight() : 0;
}
this is what I'm talking about
yes you're right
I use world.getminHeight() in 1.17+ but just "0" on 1.16
I couldnt do that when using 1.16 api
So again, no disadvantage of just bumping, right now the uscases get blocked before they can even surface
Hmm, well this is the path you need if you want to change that keybind. You can also find what keybind Alt + F1 is currently mapping to with the button that I highlighted.
if you got a better idea on how to do stuff like this without using the latest api, pls lemme know
because I don't have any better idea
Abstraction and modules would be the clean way
for such a tiny thing?
I mean that's a one-line method
I mean, sure, generally you're right, but a module for a one line method? that sounds a bit overkill to me
One or twenty, isn't it better in the end ?
Ctrl+Alt+L I think
CTRL + ALT + L
thank u
or Cmd+Alt+L on mac
Well, in your project, am sure it's not just one, right?
If it's just one you can stick to that obviously, no need for anything fancy
let me check
Not sure if you would want to do this, but you can change the keymappings. There might even be a VSCode keymap you can download.
oh yeah, components r required for actionbar, unless im stupid
And again, setting spigots fork of Bukkit to java 17 will not make that usecase impossible
I check the McVersion three times in the entire project
plus sometimes I'm doing stuff like "does method exist" because sometimes, stuff gets added "inbetween", e.g. WorldInfo#getMinHeight() was added in 1.16.5 but it's only available in one of the latest 1.16.5 versions
and some people are stupid and use outdated versions of outdated versions
I wouldn't even cater to that
all fun n games til u got .append hell
create a getGenitive(String name) method
if it ends with "s", you'd only append ' but not 's
damn
Jesus' blood
what if their displayname ends with a formatting code 
strip it of all color codes
if it ends with s, you append ', otherwise you append 's
That's why adventure for example allows you to append text and color in one call
Display name should be a component ^^
spigot-api :v no components in bukkit stuff
thanks copilot, very useful suggestion lmao
did not know stripColor existed i was almost about to write a method to do that
oh, cool
didnt think my code using Translatable was gonna be right on first try
im guessing i should use something else for if theyve named an item tho
hm I get weird errors after upgrading from MockBukkit 1.18 to 1.19 D:
Stacktrace: https://paste.md-5.net/egilufusex.rb
Line 40 in UnitTest.java: ```java
package com.jeff_media.jefflib;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.MockPlugin;
import be.seeseemelk.mockbukkit.ServerMock;
import lombok.Getter;
import org.bukkit.World;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
public class UnitTest {
@Getter
ServerMock server;
@Getter
MockPlugin plugin;
@BeforeEach
void setup() throws IllegalAccessException {
server = MockBukkit.mock();
plugin = MockBukkit.createMockPlugin(); // <--------- line 40
JeffLib.setPluginMock(plugin);
}
@AfterEach
void destroy() {
MockBukkit.unmock();
}
}
Pom.xml: https://paste.md-5.net/hozodegune.xml
Already had to switch from spigot to paper-api for MockBukkit 1.19 to run, but it's still throwing errors when doing createMockPlugin(), which worked fine in 1.18.
Any ideas? D:
well that's basically just the same as this
but without the spaces, it indeed looks funny
Yeah thats my annotation to tell people this will only work on paper
For javadocs and stuff
o
I wish I could find a way to automatically generate the javadoc tag from the annotation but I haven't found an easy to do this
currently I need to add both the annotation, and the javadoc tag, and I hate that
if anyone knows how I can make javadoc generate the tag automatically from the annotation, pls lemme know
in the meantime I'll drink some more coffee until I get cardiac arrhythmia
If you want the majority of the api to be sealed and if this is what paper does all the more reason to not use it if it just restricts extending it. Purpose of an api isnt only for something to be used but the ability to extend it if necessary
yeah, even if it wasn't meant to be extended, why disallow it?
e.g. the Enchantment class
Depends. Sometimes it will complain. Especially if you are shading. In general you should not bump java version if there is no inherent need or not making use of anything in the higher jdk versions
This true in most languages. Always make use of the lowest version possible and only bump if necessary
look i really need some help. I'm making a plugin and I have events registered that only work in a certain world (a multiverse plugin world) in my testing server everything works, but in the actual server, the events dont work at all. What do i do
hello.
?notworking
"Does not working" is a useless statement. Please describe what exactly is not working, what you expect it to do, and what actually happens. If you get any console errors, also ?paste the entire stacktrace.
What happens to UUIDs when a server runs with online-mode=false?
the events do not get registered
Make sure you have the same plugins and versions on both
The server uses offline uuids instead of online ones.
what is the difference?
show your code
For players they are generated using their name as part of the generating uuid. They are not fetched from mojang servers
they are randomly generated from the name or sth
The calculations used. Online is also registered with mojang servers. So it acts as a form of verification.
Difference being offline uuids are not guaranteed to be unique. And anyone can use whatever name they want.
okay, i have this database where i am storing UUIDs. Now I need to test some stuff with 2 players probably but i don't have second minecraft account so I might try running the server with online-mode=false and join with a second minecraft instance.
yep, knew that.
not UUIDs, just the usernames.
Best to just use online mode. We dont support offline mode servers
probably won't run this in for online-mode=false during production but i need to test stuff right now.
Correct
so, what happens to UUIDs that have been previously registered?
What do you mean?
say i join with the same username on both offline and online modes, do they both get different UUIDs?
Yep
Yes
ok.
which code exactly?
downgrading the paper-api dependency from 1.19.3 to 1.19.2 fixed this
anything related to your events
ill put one
btw with "registering events", do you mean event listeners, or did you write actual event classes?
public static void onPlaceKey(BlockPlaceEvent event){
if(event.getItemInHand().getItemMeta().equals(ItemManager.key0.getItemMeta())){
Bukkit.getWorld(world).getBlockAt(event.getBlockPlaced().getLocation()).setType(Material.AIR);
if(event.getPlayer().getGameMode().toString().equalsIgnoreCase("survival")){
event.getPlayer().getInventory().addItem(ItemManager.key0);
event.getPlayer().getInventory().removeItem(ItemManager.key0);
}
}
if(event.getItemInHand().getItemMeta().equals(ItemManager.key1.getItemMeta())){
Bukkit.getWorld(world).getBlockAt(event.getBlockPlaced().getLocation()).setType(Material.AIR);
if(event.getPlayer().getGameMode().toString().equalsIgnoreCase("survival")){
event.getPlayer().getInventory().addItem(ItemManager.key1);
event.getPlayer().getInventory().removeItem(ItemManager.key1);
}
}
if(event.getItemInHand().getItemMeta().equals(ItemManager.key2.getItemMeta())){
Bukkit.getWorld(world).getBlockAt(event.getBlockPlaced().getLocation()).setType(Material.AIR);
if(event.getPlayer().getGameMode().toString().equalsIgnoreCase("survival")){
event.getPlayer().getInventory().addItem(ItemManager.key2);
event.getPlayer().getInventory().removeItem(ItemManager.key2);
}
}
if(event.getItemInHand().getItemMeta().equals(ItemManager.key3.getItemMeta())){
Bukkit.getWorld(world).getBlockAt(event.getBlockPlaced().getLocation()).setType(Material.AIR);
if(event.getPlayer().getGameMode().toString().equalsIgnoreCase("survival")){
event.getPlayer().getInventory().addItem(ItemManager.key3);
event.getPlayer().getInventory().removeItem(ItemManager.key3);
}
}
if(event.getItemInHand().getItemMeta().equals(ItemManager.key4.getItemMeta())){
Bukkit.getWorld(world).getBlockAt(event.getBlockPlaced().getLocation()).setType(Material.AIR);
if(event.getPlayer().getGameMode().toString().equalsIgnoreCase("survival")){
event.getPlayer().getInventory().addItem(ItemManager.key4);
event.getPlayer().getInventory().removeItem(ItemManager.key4);
}
}
}```
?paste
this is in an event class
Use the paste link please
so in my testing server it works
it's a listener, not an event class
oh dear Christ
btw have you ever heard about loops? o0
Lol
why is there 5 times the exact same code
they're different
yeah you changed one number
Yea, but the bulk of it is the same.
different item
use a proper loop pls lol
I mean, what are you gfoing to do if you wanna change one line? change it 5 times?
uh
Holy fuck
how do i create two different offline mode usernames?
and launch instances of minecraft with those?
I think you need to have the launcher disconnected from the internet and login with mojang authentication.
Password shouldn't matter if it's offline.
- why is the class called "KeyEvents" if it doesn't declare any events but only listens to existing ones?
- You didn't show how you register your listener
- Stop repeating yourself thousands of times, that is extremely bad code.
my theory is that cause before I was getting an error cause the world I was trying to load was coming back as null (since it wasn't loaded cause it was a multiverse world) so i added code in my main class and it works now but I think that it still comes back as null just no error
all of this could be done with 3 simple for loops within like 5 lines
Well, what's the stacktrace say?
the listener is definitely registered. probably one of your thousands of if statements evaluates to false, probably ItemMeta.equals(ItemManager.keyX.getItemMeta())
also erm, why do you store the name of the world, only to do Bukkit.getWorld later on?
why not store the world directly?
Because it leads to undefined behavior
And no, thats not what paper does for existing API
String world = myWorld.getName();
Bukkit.getWorld(world).... // This is pointless
i had it different
Isn't that on those who extend it though? At that point it would be their fork of the API no?
idk the whole class is a total mess, I'd rewrite everything from scratch
Not keeping API and server in sync is so backwards tho
i can
just the issue isn't it not working
it just doesn't work in the server i add it to
I mean, you should reasonably protect people from doing wrong stuff
it works in the test server
Probably an itemstack
if so, it'll only work if the durability is the same
you should identify your custom items by PDC tags instead of comparing the item meta
I've been busting my ass off trying to find a nice, clear and consise explanation for how the nbtlongarray in region file's section chunks is formatted / how it applies the pallete to say which block is where.
I can't think of anywhere else to ask to get advice on where to find said guidance?
idk how to use PDC lol
?pdc
confuses the fuck outta me
why are yo ucheckin the command's name? are you using the same executor for different commands?
i thought that's what ur supposed to do
there are multiple args but yeah
also why are you printing "This is not a valid entity" when Integer.parseInt fails?
shouldn't it rather print "That is not a valid integer"?
min is 1 max is 4
You only need to check the command name if you have multiple commands registered to the command class. Otherwise there is no need to check it. 🙂
you should learn how to use for loops tbh
i just grouped it with the amount cause if its 0 or negative it gives same message
i will have multiple commands there
this is early
in one executor?
Actual commands or subcommands?
Thats a funny way to spell "streams" 😉
why don't you just use one executor per command
in one class
but why
Saving potion effects on death and giving them back on respawn
There is a good video series on command managers to better structure multiple commands into an easy to add to structure ^_^
less classes idk
Do you know about abstract classes?
but still these things are the issue
yes
the code works
it just doesnt work in the server im adding it to
so it must be something to do with other plugins
probably multiverse
having less classes is usually a very bad sign
imagine you throw everything you have in one drawer instead of having separate drawers for socks, underpants, tshirts etc
sounds pretty stupid
It's likely one of two reasons.
- The world isn't correct.
- The items you are comparing against don't have the proper data.
So you should really start putting debug messages in places to see where code execution stops.
Oh right interesting.
Honestly follow the rule I learned in the engineering industry.
You could beat ur skull up the wall for literal hours trying to find the problem.. or you can have a mega brain and remove each plugin one by one (or add 1 by 1 to another server) until you find the problem
or check out EventDebugger
binary search be like
its not the items cause it works in other servers
Lmao sometimes it's saved literally 10000's dollars so :L
I remember the time a lands plugin bug where land titles were not showing up was, I shit you not, caused by a loop in a datapack that had remained unused for over 4 months, in 1 file..m for the zoom in of a musket weapon reseting titles....
Sometimes stupid shit is only found via the shot gun approach haha
Start debuggin then. Sysout the world name that Bukkit#getWorld() is grabbing. If it's not the world you are expecting, then we'll go from there, but we can't really give you a solution without getting some more information.
lol
Look if literally nasal can waste millions of dollars by, I shit you not, converting from metric to imperial wrong when doing thrust calcs, leading to a Martian prove burning up in the atmosphere, we as spiggot devs are not gonna avoid the stupid shit either haha
tbh debugging that code is pretty much a waste of time, they shuold first rewrite it to be working "generically" instead of hardcoding every single thing with thousands of duplicate lines
What you call a waste of time, I call "he is never gonna learn how dumb the dumb stuff is, till he has to debug dumb stuff "
also true
also how would i make a reload command that updates the plugin and adds the changes without me having to restart the server
the server im adding it to doesn't let u do /reload or /reload confirm
This entire field is built on having to clean up after shit code , including our own. Don't take that away from him 😉
usually you can just call reloadConfig() if you grab your values from there during runtime
if you cache them somewhere, then cache the new values again
Assuming that they are using the default config though.
however caching it is usually pointless as getConfig() is basically just a Map<String,Object>
I wonder how many builds it'll take until this test fails lol
https://paste.md-5.net/genoroqive.cpp
i dont understand that question
Can you give some context ?
also why are you using NBT tags instead of PDC?
im using the one you sent me yesterday
I definitely didn't send anything about NBT
hey, im trying to interact with my custom block, for example right click and it does something.
?blockpdc
Learn about CustomBlockData here:
https://www.spigotmc.org/threads/custom-block-data-persistentdatacontainer-for-blocks.512422/
it is PDC
ah ok. well then, why would it be a problem to check it from another class?
the tag name
if "it's red", there for sure will be some proper error message if you hover over it
are you passing the plugin instance in?
also wdym with tag name? do you mean the NamespacedKey?
yes
create a field in your main class for the namespacedkey, then pass that key to all the instances where you need it
or pass your main instance instead and get it from there
is there a built-in way?
@tender shard so i've determined it's not an issue with the worlds
I suppose its personal preference on this part
without any external repo?
no
are there are plugins that completely disable events
if there'd be a builtin way, I wouldn't have spent hours writing CustomBlockData lol
I dont get it how do i access a NamespacedKey created in a different class
you could just look at a minecraft picture instead
wdym with "disabling events"?
ofc one could write a plugin that deregisters all listeners for any event, but why would anyone do that?
how do i check for the pdc tag from a different class please help
I have sent you my blog post about DI / static getter twice already
i dont know how to get the tag tho
btw that's not true for everything. Material#getTranslationKey() is marked for removal although it's part of bukkit:
Nah cause I wanna know why my events arent working
theres better ways to debug
what do you mean by "arent working"
Example I have an event that makes a block disappear when you place it
In my testing server it works
- declare a field in your main class, either public or with a getter, that holds the NamespacedKey
- check my blog post to pass your main instance to other instances, then you can use it to get your namespacedkey
alternatively, you could just pass the tag instead of the whole main instance
So why does it work in one place but not another
its the "use it to get your namespacedkey" part i dont get
public class MyPlugin {
public NamespacedKey myKey = new NamespacedKey(this, "myKey");
public static MyPlugin instance;
{
instance = this;
}
}
Other class:
public class OtherClass {
@EventHandler
public void doSth(SomeEvent event) {
NamespacedKey myKey = MyPlugin.instance.myKey;
}
}
that's the basic idea
usually you'd want to use a getter instead of public fields, but the idea is the same
It would be weird if it wouldnt work lol
Ugh the whole make a singleton with a public var instead of a static var class
as I said, it was just an example to show it in the most compact way lol
probably the most simple version thb
I also sent my blog post that also explains proper DI sooo 😄
Don't even need DI. For keys I'd make them in a static class
are you using the fromString method?
it would also be possible to make a get method just a note
because for the constructor you need the plugin instance
- dependency injection
takes main class (Main Main)
setter for other classes
yo
i keep get an `Error: internal error: (java.lang.exceptioninitilializererror) this is first time setting up a spigot plugin so any more experienced guys know if theres like a common cause to this?
alr guys what is the safe way to store bukkit runnable threads?
i'm learning to make multi threads
Depends on how you'll access them?
So where do runnables come in?
It's more helpful if you share the full error stacktrace
yea yea true idk thought i was making some simple mistake lmao
hands up confused thb i dont know
possible to link me some source?
Don't look at me you asked
i literally got no clue
that is alright
Then dont store them and instead use your own threads
i just assume using bukkit and not java threads hmm
Bukkit just extends runnable and thread which you can do as well. If you have to store runnables might as well just have your own threads to make it easier
help that guy
sorry my computer isnt letting me put in text doc
that is a text link
Thats fine, just put it at that link and remove it from here
Thank you
yeah if anyone knows whats going its literally just an onenable and on disable method in the code lol
Use oracle jdk
yeah i am
Then not sure why its complaining about not being able to use a sun package
java.lang.ExceptionInInitializerError: Exception java.lang.IllegalAccessError: class com.intellij.util.io.FileChannelUtil
What java version are you using?
1.19
Certain you dont have another installed that it is being used instead?
https://paste.md-5.net/ucudariwar.java this is the code btw lol
yeah i just installed it today
cause i usually use 1.8
I would try downgrading to java 18
i did as well lol
Weird
Welp have to wait for someone else who uses intellij i dont use it
@tender shard any ideas?
ah yea i figured it was sm to do with intellij being dum
Well it says in the error that it is something with intellij
yeah may try it in eclipse
I personally use netbeans
ill try that then ive heard its pretty good
Because i like its layout and i dont encounter any of the problems thst others have with intellij.
Also i can fine tune its resource usage as well
me neither 😏
basic eclipse user
Or optimize it
I can even specify specifically which jdk to use for it too
real
i wanna learn intellij so i can become a better dev
But like i always see people with intellij have cache problems or maven issues. In netbeans i have neither of those problems at all.
thb the pain of learning it
intellij doesnt make u a better dev lmao
being able to understand more ides helps bruh
Using an ide that is comfortable for you makes you a better dev
yea
You dont need to use these other ides if you dont want to. Doesnt change your understanding of java or how you can use the code
just expanding my knowledge lol
hey @wet breach how would I store my threads
what is safest way if i wanna access them
A list? A map? It really depends on how you want to access them
cancel?
alright i just go ahead figure something out
while making it
You can either store the thread object in a list or map or store the thread id.
I would store the thread object if its a daemon thread and ids for all the others
And then ideally you want to make threads that are not daemon threads self cancelling
And then daemon threads should have a loop where it checks a boolean if it should close out. Not that it makes much difference but should. Main thread will force close daemon threads when main thread is shutting down
You can set the kind of thread it is when creating the thread object
Welp time to go home for me 
how do i identify the cause of my plugin not working?
does it spit out any exceptions from console?
or did you do the human error
missing code or misspelled?
The hard part about multi threading isnt actually the making or tracking of threads. Its making sure you dont encounter deadlocks and cme's as well as occasionally race conditions. On top of that it is also ensuring you are not spawning too many threads and dispersing the work load adequately between them if that is the purpose of them. Threads require ram to be created. So with defaults and not much in your thread class if you spawn 1000 threads its going to require and consume just over 3gb of ram
Well it does say what the problem is
i cant read
did you remember to export it correctly?
with the plugin.yml
YourPlugin.jar/plugin.yml
Decompile? O.o
Well you are also using purpur
Click on project and export
So if it worked before then might want to see about that fork you are using. This is spigot
it is
Doubt its the plugin.yml causing a cast exception
Its more likely they are trying to instantiate their own main class or casting the main class instance
java.lang.ClassCastException: class me.Danko.CSTMItems cannot be cast to class org.bukkit.plugin.Plugin
Looks like you are shading somethgin you should not be
meaning?
Could be that too
what's the issue
?nocode