#help-development
1 messages ยท Page 358 of 1
i did, but is it just magically gonna appear in my project code now
You need to declare them in the maven pom
I mean players nametag. How to add prefix above player skin. I try to create packet scoreboard team, but I don't know how to edit this.
mysql is shipped with the server 
ohh wait
set scope to provided ig?
do i have to set them to provided
Or gradle
yeah
i'll also be doing mongodb ๐ญ
probably some outdated version
this took longer to understand than it should've lol
thx
Hey guys, I was interested in adding bstats to my plugin, but I notice when I give it scope compile in maven, it takes my jar size from 12kb to 9mb. The documentation says to use scope compile, but isn't bstats included with every spigot distribution?
no, bstats isn't
and it shouldn't be 9 mb
at most 1mb
something else does that i'm pretty sure
hmmmm, I wonder what is going on here
i use this:
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.0</version>
<scope>compile</scope>
</dependency>
my plugin is only 1.8mb
?paste your pom
and it has many other deps
hmmm, very strange I wonder why mine is getting up to 9mb
lemme try to rebuild it
what in the world ><
bstats y u do dis to me lol
How can i make players stop interacting with blocks but without blocking the item interact?
Like using the shield
?paste your pom/gradle
original is without shaded stuff
^
So the problem was I had lombok in there as a compile dependency. However, I was not using lombok at all in my code, I just had it in there as a holdover from a few years ago. I guess the regular compile was realizing it was unused and omimtting it
But for some reason the shaded version was still including it
just completely removing lombok fixed it =]
lombok is only like 2mb
It was definitely the problem though haha, no idea why
but yeah it is tiny
but now im back down to 20kb
thats what she-
๐
That was my thought as well, but for whatever reason that did solve the problem lolol
It's surely because I was including it as <scope>compile</scope>
like a psychopath
bad iea
lmaoo
have lombok included in your plugin just in case the compiler fails to read the annotations
nice foreshadowing from your past self
i shade it in my lib so i dont have to remember to add i
One final touch before I put this update out =] I want to make my console text light yellow like a lot of plugins do when it says "Update available"
do I just need to use color format codes as if I was sending an ingame message?
You can use ChatColor, im pretty sure that works
will look into that, lets see here
How can i make players stop interacting with blocks but without blocking the item interact?
๐ค
hmm ok so using chat color does seem to add the correct formatting code, but it does not change the color in the console
how are you using it in the code?
console coloring doesn't really work like that
For example, right now if i cancel the interact event you can' t use the item in hand to, for example a shield or something like this
Oh I see. If you use Bukkit.getConsoleSender().sendMessage() it works
Ahh gotcha, yeah I want only the server admin to see this one
I think that would work if you were sending it to an ingame sender
But I think I prob gotta do some weird shit with ANSI colors for console maybe?
no that works and only puts the message in console afaik
Oh no kidding
lemme give it a shot
You are quite right =] however it doesn't include my plugin name in brackets automaticaly anymore, but thats no big deal at all I can add that =]
thank you!
no problem, there is most likely a better way btw XD
haha there always is =] I'm just glad to see some things working
you shouldnt be using color codes in the terminal
how should I achieve the colored text in terminal? I often see plugins doing it to draw attention to updates being available
Just make an "UpdateAvailableException" Kappa
Hi, guys I have this problem, I am making plugin with elimination. So when the player gets eliminated, player gets kicked and cannot rejoin the server. When player is eliminated, file is created in specific folder. Here's part of code:
@EventHandler
public static void onJoinCheckIfEliminated(PlayerJoinEvent event) {
Player player = event.getPlayer();
File checkFile = new File("plugins/LifeStealCore/eliminated-players/" + player.getUniqueId() + ".yml");
if (checkFile.exists()) {
player.kick();
}
}
}
Everytime eliminated player tries to join, he is kicked but I get this error:
Couldn't place player in world
java.lang.IllegalArgumentException: arraySize cannot be negative but was: -1
etc.
I would use PlayerLoginEvent
Otherwise you would probably need to delay the kick I think
?paste the whole error
Ye, i was thinking about banning, but i prefer kick i guess
Use PlayerLoginEvent then right
so new File("eliminiated-players")
since when
Then the above one works too
I'll try use that method in a moment and will keep you updated
pre join event looking like
yea whatever, im out of date in general, just PlayerJoinEvent is not right lol
What could be the best way to store the mysql credentials?
just plain text in the config.yml?
yeah
id rather not have a separate file for each player
that does seem really pointless
creating a file for each player that gets eliminated
files are empty, so i guess searching for file is better than looping for every record in one file (?)
ye, that makes sense as well
So, I give myself a bucket with this command /give @s minecraft:water_bucket{CustomModelDala:1000000}
This is my if statement and it doesn't run if(Item.getItemMeta().hasCustomModelData() && Item.getItemMeta().getCustomModelData() == 1000000 && Item.getType() == Material.WATER_BUCKET)
Whats wrong?
CustomItemDala
about that, any link, how to make dynamic yml file etc. ?
The Configuration API is a set of tools to help developers quickly parse and emit configuration files that are human readable and editable. Despite the name, the API can easily be used to store plugin data in addition to plugin configuration. Presently only YAML configurations can be used. The API however was designed to be extensible and allow ...
conclure writing chapter 2 of the bible
?configs
See this wiki page on how to use custom configuration files: https://www.spigotmc.org/wiki/config-files/
that site sucks
//resolve the right path object
Path pathToDynamicFile = plugiun.getDataFolder().toPath()
.toAbsolutePath()
.resolve("dynamicfile.yml");
//check if the file does not exist
if (Files.notExists(pathToDynamicFile)) {
//create it
Files.createFile(pathToDynamicFile);
}
//new config object
FileConfiguration config = new YamlConfiguration();
try (var reader = Files.newBufferedReader(pathToDynamicFile)) {
//loading the values from the file into our config objectr
config.load(reader);
}
//config is now usable
@small hawk
iirc the spigot and bukkit wiki uses legacy file api but here's a quick, updated 1
var is fine there
is new File(JavaPlugin.getDataFolder(), "file.yml") legacy now?
File is a bit legacy, not deprecated but Java advocates to migrate to Path + Files
target
for instance File#listFiles can cause dos, and File#rename did not work consistently across different os
update the wiki
This Java tutorial describes exceptions, basic input/output, concurrency, regular expressions, and the platform environment
any build errors
average programmer
is it possible to create a Tab Completer that can not be auto completed
so it just suggests the next word but you cant press tab to write it?
Is it possible to access target uniqueID, when player is offline, by running command in console?
How could I fix this? I want the text to be the same on the first image as the second image
hologram.setVisible(false);
hologram.setCustomNameVisible(true);
hologram.setCustomName(ChatColor.Green + "1 coal generator");
hologram.setGravity(false);
hologram.setInvulnerable(true);
This is what I currently have
target/
Try Shift + F10
open the top drop down
then package
open it
open the top drop down in that
that wasnt the top dropdown then
should look like this but with different tasks
show what it looks like
can anyone help?
like minecrafts commands?
yeah
bridgadier
bridgadier
fuc
god my pc
what are some good hologram plugins/api folks use here
for newest version
1.19+
okay
I guess I can take a peak at the source of other ones
decent holograms
we will roast the fuck out of you
still need help
ll i see different is ones green, ones black
and this is for the first or for the second picture?
the black one is actually green is you look closely
I want the text in the first picture to look the same as the second one
and your code created the hologram in the first or in the second picture?
oh wait
that is so jank
the way that exists is because the armorstand is in a block
so the text is dimmed
is there a setting that can fix this?
put the armorstand above the block
mvn install:install-file -Dfile='CMI9.0.0.0API.jar' -DgroupId='com.zrips' -DartifactId='Zrips' -Dversion=9.0.0.0 -Dpackaging=jar
token that is specified in the parameters at startup
I have my own launcher and I want to make my own authorization
Also this is Spigot related.
Not MCP or this stuff
that pom would be incorrect, do it in an empty folder
put the version in quotes too
mvn install:install-file -Dfile='CMI9.0.0.0API.jar' -DgroupId='com.zrips' -DartifactId='Zrips' -Dversion=9.0.0.0 -Dpackaging=jar
oh miss
oh my
Guys
To avoid cheaters, griefers and etc.

Who write plugins for Minecraft?
almost everyone in this chat, but this is not the place
?services
If you wish to request or offer development/art/building/administration services, please do so at https://www.spigotmc.org/forums/services-recruitment-v2.54/
Who can write a plugin? Compound
ask on the link
But anyone can bypass the ban and ip ban
this is the wrong place to ask for commissions
?services
If you wish to request or offer development/art/building/administration services, please do so at https://www.spigotmc.org/forums/services-recruitment-v2.54/
Could someone give me a quick tip on my issue?
I'm using protocollib to listen for outgoing chat messages which I might want to delete. So I setup an intermediate cache for storing the messages that might be deleted, but I'm running into a concurrency issue with it. Could someone give me a tip on how I could either make the outgoing packets be synchrounos or rather, preferably, give me some advide on how to make a cache that can handle asynchrounous calls.
For record, I'm using a LinkedList as "cache".
Ordinary stupid griefers and cheaters will not be able to
Cause I can't listen for server sent messages via the normal Event API
Or can I and was just blind?
I want to delete a "message block" sent by a plugin.
But I only want to do so if there is a certain message within this "block".
Any clues why it throws this, even tho I have scope compile?
if its a bungeecord plugin you need bungee api
bungee is different api
The official Krypton Maven repository, containing many of Krypton's published artifacts, as well as some other projects.
bungee is on there
Hey guys, I am trying to convert some code that I wrote earlier from using protocol lib to just using base NMS. I have been able to implement the packet sending successfully, but I can't find any good examples for how to write a packet listener. Any reading material or examples you can suggest? Thanks in advance =]
Ok, I think I solved it
how do i use luckperms with a treemap?
TreeMap<Group, Integer> sorted = new TreeMap<>(groupMap);
How can I check if a player has an inventory opened?
player.getOpenInventory() != null
god is sure is difficult to test multiple versions on windows lmao, how am I supposed to switch to lower java versions haha
im switchin over to linux for this good lord
just specify the path to java.exe
just specify the path when you launch

fair enough lol but openjdk builds aren't provided for anything below 17 anymore ><
?java17
Install Java 17 at https://adoptium.net/?variant=openjdk17&jvmVariant=hotspot
I'm just gonna switch over to linux and use archlinux-java script lol, its easier for me
good to know though
they go all the way back to 8
same as this except that lets you pick version directly
now that im working with packets im super scared im going to break somebodies shit if they try to install on an older version lol
player.getOpenInventory() != null is always true
If the player has an inventory opened or if he is just doing things in the world
You can't tell
You can tell if they have a specific inventory open, but nothing else
o.O
why is player.getOpenInventory() == null false even if the player has no inventory opened?
read the javadoc
ah it returns a view
it tells you
cant you check if the top inv is null, meaning the player doesnt have an inv open?
bruh its notnull too
no, they could have their inventory open
Would it work if I would check if the size of the TopInventory is smaller than 1?
no
why?
I already told you
You can't tell if the player has no inventory open
It will alwasy return a View wether they have an inventory open or not
Hey guys, is there a way to tell my maven to build multiple times, using a different java version each time? I need to build with java 11 for 1.16 and below, and would like to not have to switch back and forth manually
ah, I think I found something. I need to specify multiple toolchains
hello, can anyone help about the Spawner plugin?
Ok guys, point me in the right direction please. I want to support older versions of minecraft. But when I try and use my jar file in older versions it complains about Unsupported class file major version. I am compiling using java 19 for 1.19, and I prob need to go back to around java 11 for older versions. How do you guys handle this?
set source and target for the compile plugin
Will I need to do that manually for each build?
you build for the oldest java you want to support
Ohh I see, so I set source to java 19, and target to java 11
Ahh gotcha, but newer versions say that 11 is deprecated
so I need to build two versions of the jar? I see some plugins that have a single file that supports from 1.13-modern
so I'm a bit confused haha
I think I need to get mc 1.13 on my local maven repo with build tools and target that
What exactly do you want to do @trail lintel ?
well, I am trying to get my plugin to support versions as far back as possible
although I do notice the packet structure has changed quite a bit as far back as 1.13
1.12 is a whole different world
You need to write your classes in the oldest version of java that the game will run for those older versions. I.E. Java 8.
That being said I don't recommend compiling your plugin with two different java versions
so then what about newer versions of the game? They won't run because it says you need at least java 11
Use one and if really needed use java 9's multi-release feature
they do not.
Plugins will run just fine. The game and the server itself need the newer versions which can be done with different file paths.
Or well they do but the JVM can load classes from earlier java versions
Ohhhhh I see
ok that makes sense, thank you =]
ok one final question
I notice that net.minecraft.world.inventory.Containers does not exist until 1.18. How can I have it to where that import is only used if a certain version of the api is detected? I imagine this will have to be part of the build phase, not runtime.
But my maven-fu is pretty bad
You'll need to setup a multi module maven project if you need version specific code.
I will look into that now, ty!
Anyone here had an issue before with YAML and windows system languages? For some reason whenever someone with a turkish computer tries to use my plugin the code reads "i" in the configs as "รฝ" which breaks everything.
save yaml as utf8
Will check thank you ๐
hmm so if I use these submodules, will this build multiple versions of the same jar?
no
I would like to have a single jar that can intelligently do the correct imports if possible
there is no such concept as imports at runtime
Hell they don't really need to exist at compile-time either
The correct term would be to load the correct classes, but that is rather straightforward: Only classes that are used are loaded. So if you never instantiate a class (or reference it in any other way ||there is an exception to that rule due to javac inlining||) it will never load the class thus not complain that it does not exist
A multi module project will build jars of each module, but will also create a combined jar like you are wanting once you setup the poms.
you hide all your version specific code behind an API
each module is version specific and implements the API
then in your main plugin class you instantiate whatever version class/API you need
Does anybody have an example pom I could look at? I am a bit overwhelmed by this concept, although I do get the idea you guys are talking about. So the jar WILL contain code relevant to all versions, but because its not being called it will not throw an error
A project that does it that I know of is https://github.com/Zedly/Zenchantments
yessss this is for NMS too, thats exactly what im dealing with as well
causing a huge pain haha
It's old NMS though
You can treat each module as the specific version you are working on. Since each module needs its own pom, you'll just define the spigot version you need to work with. The tricky part is avoiding cyclic dependencies when you merge them all together in the parent pom.
1.15.2 were very different days. Up-to-date versions of that plugin either dropped multi-version support or dropped NMS
I just need to get the concepts though =] I can adapt this I believe. Great resource to look at
I'm sure I will run into that shadow haha, one step at a time though!
yeah geol I notice the package structure is COMPLETELY different from 1.18-1.19
The compatibility adapter is created by https://github.com/Zedly/Zenchantments/blob/master/Zenchantments/src/main/java/zedly/zenchantments/Storage.java#L43-L75 for reference
like shockingly different lol
mojmap?
I am using decompiled spigot from buildtools atm
I only need to send one very simple packet, so I don't need full mappings really I don't think
It's not so hard nowadays due to the mappings and screaming sandals.
my plugin does this when i try loading it even though in the IDE ive set language level to 1.8
Finding the packet you need is a lot easier.
How are you compiling it? Maven?
I personally would use mass ASM (instead of reflection) if spigot was to support it, but it is a bit dangerous with the bundler and paperclip and all
gradle shadow
Oof. I don't use gradle. However I'd check your gradle compiler settings. It probably takes precedent over the IDE compiler.
Remind me what ASM is?
Correct. Vice-versa can also be true
OW2 ASM, bytecode modification framework
Man I have learned a lot today lol you guys rock
Mass ASM is the practice of reading and writing a larger amount of classes. If done wisely it can be much safer than reflection, but unfortunately it is so shunned that next to no modloader actively supports it without also having a witchhunt alongside it
I'm on my way to compatibility for older versions =]
Are you aware of the 1.13 Material refractor?
I am not ๐ฎ
XMaterial can be used to mitigate that.
If you are using itemstacks you'll be up to a big surprise then
oh god I am lol
Yea, that alone is why I stuck with XSeries for my multi version projects. I didn't want to setup extra interfaces for items, sounds, and particles.
fortunately my plugin is tiny, it only adds a single item. But I will definitely look into this xseries thing
would this do it? this is all i can find online about gradle language level
that is an odd syntax
kotlin gradle
yeah
I really wouldn't know since I use maven for all of my projects. That looks like it might work, but maybe something like gradle compiler source would be the better option if something like that exists.
Ah. In groovy gradle it'd be
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '11'
for Java 11
normally i just use JavaVersion.VERSION
Reload the pom?
how?
Hello everyone
[23:46:14 WARN]: [AnimatedMenuPlus] Failed to load menu file shop.yml!
[23:46:14 WARN]: [AnimatedMenuPlus] me.megamichiel.animationlib.config.ConfigException: Couldn't load shop.yml
ok
Does anyone know why when using the ? syntax in mysql queries, it will sometimes append extra apostrophes to the query?
Som1 know how i can watch the patern of the craft (like "C C" "CCC "CCC" for a chestplate) with CustomModelData
@EventHandler
public void onPrepareCraft(PrepareItemCraftEvent event) {
CraftingInventory inventory = event.getInventory();
ItemStack[] matrix = inventory.getMatrix();
int count = 0;
for (ItemStack item : matrix) {
if (item != null && item.getType() == Material.CLOCK && item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
if (meta.hasCustomModelData() && meta.getCustomModelData() == 2) {
count++;
} else {
// This item is not an รtincelle Aquatique with customModelData 2
count = 0;
break;
}
} else {
// This item is not an รtincelle Aquatique
count = 0;
break;
}
}
if (count == 9) {
ItemStack result = new ItemStack(Material.CLOCK);
ItemMeta meta = result.getItemMeta();
meta.setDisplayName("ยง3Lingot Aquatique");
meta.setLore(Arrays.asList("ยงbItem Aquatique"));
meta.setCustomModelData(3);
result.setItemMeta(meta);
inventory.setResult(result);
} else {
inventory.setResult(null);
}
}```
RecipeChoice.Exact, recipe api
Is there any API for signs gui yet
there is a pr
Hello, is there a way for me to use the obfuscarted sources instead of the mappings?
I have thi son my pom:
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.19.3-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
But it's bringing up the mappins, i really need the normal obfs NMS
that should being up obsfucated stuff
Can't
Can't legally sign cla
I don't see any remapping, as long as you're not running SpecialSource you should be able to see the regular stuff
"yo dad this might seem odd but I need you to put our full name and address as I want to make a PR"
is that what you did
So the PacketPlayerInfo was renamed to ClientboundPlayerInfoUpdatePacket?
Yeah
Packets made in the later versions
are renamed
old packets are still kept the usual
So you now have PacketPlayOut and ClientboundWhatever
sounds good, thanks
"Why was my server using 70% of 24gb of ram with barely any players on" :The "Raz forgot to turn this on in server properties" story
Hi, I wanted to update one of my plugins which is utilizing NMS to 1.19.3
I built the remapped jar using builtools (executed using java 17) and my entire maven project as well as my IDE is set to Java 17. However, when building (at the stage of remapping) at keeps throwing me the major version version 63 error, which means that a class file is on java version 19 (but maven only supports up to 17 afaik)
Does anybody know how to change this?
[INFO] --- specialsource-maven-plugin:1.2.3:remap (remap-obf) @ SimpleNPCs ---
Adding inheritance C:\Users\trxss\.m2\repository\org\spigotmc\spigot\1.19.3-R0.1-SNAPSHOT\spigot-1.19.3-R0.1-SNAPSHOT-remapped-mojang.jar
java.lang.IllegalArgumentException: Unsupported class file major version 63
Hey guys, so I have been working on getting a compatibility layer set up for my NMS functionality. I set up multiple maven submodules for each specific version of minecraft I am targeting, each with their own pom with the relevant spigot api and minecraft code. But I'm wondering, is all this submodule stuff overkill? Couldn't I just include all the versions of the api/base that I need in my standard pom and have them as scope provided?
Separating it into modules is ideal
Because certain API features changed
Within spigot
For example, on 1.8 you have Player#getItemInHand
In the latest versions you need to get the main/off hand from the inventory
they should be scope provided anyway
On 1.8 you need to use packets to send titles or actionbar messages (or even boss bars)
On 1.9 it's native
if you only use the api you can just use 1 api, if its nms you need all you want to support
But like, couldn't I technically just have them all as scope provided and then do a switch on the relevant version string to instantiate the correct interface?
and just have all the versions of spigot api / minecraft base that I need in the root pom?
Seems hacky
rather than mess with all this submodule stuff
sub module is better
I wouldn't say it's ideal
Here's an alternate environment where submodules are ideal
Ok good deal, I will continue with submodules =]
Let's say you're hooking into a plugin with 2 major versions
But I mean regardless of what method I pick, I'm still going to need to do a switch on version string to instantiate the correct interface right?
For example, Worldedit for 1.8 - 1.12 is very different from 1.13+
One uses the BlockVector#at, the other uses a constructor and all
It becomes a pain to do it in the root module
Because it's the same class under the same package
the example I have been following
https://github.com/Zedly/Zenchantments/blob/master/Zenchantments/src/main/java/zedly/zenchantments/Storage.java#L43
Yeah
That is essentially what I'm going to have to do right?
Ok very good, I will continue with how I am doing it then. Thank you guys =]
Very close to getting my backwards compatibility back haha
I had to fix localization for that man =] He asked I must deliver
my spigot jar only has bukkit.craftbukkit.boostrap stuff in it, how do I get the other library stuff necessay for plugin development?
Bootstrap Jar
The main spigot-1.18.jar is now a bootstrap jar which contains all libraries. You cannot directly depend on this jar. You should depend on Spigot/Spigot-API/target/spigot-api-1.18-R0.1-SNAPSHOT-shaded.jar, or the entire contents of the bundler directory from your server, or use a dependency manager such as Maven or Gradle to handle this automatically.
Please read the release notes for further information: https://www.spigotmc.org/threads/9-years-of-spigotmc-spigot-bungeecord-1-18-1-18-1-release.534760/#post-4305163
maven or gradle is better
isn't it a bit of a pain to get NMS with maven tho
i built spigot through buildtools and it only has the bootstrap tho
use the stuff on there if you want unobsfucated stuff
is there an event I can use to constantly leave a chunk loaded?
ChunkUnloadEvent iirc
gfukc y
my pc
declaration: package: org.bukkit.event.world, class: ChunkUnloadEvent
so get the chunk that is being unloaded and set it back to loaded again
and it just keeps repeating?
can probably get the chunk and load it again
is there like a event I can use that is constantly running?
in ticks?
and do it like that?
if you get the chunk and load it again on the unload event osmewhat
som1 know why this isnt working
For do a custom craft with clock with custom model data 3
You could try cancelling that event, as it seems like this prevents chunk unloading. Definitely add a debug log when you cancel, to make sure that it doesn't end up in a spammy loop. No idea how chunks are handled internally. I don't know whether cancelling the chunk unload re-sets it's lifetime.
(my main)
https://paste.md-5.net/oqudecizow.java
What isn't working? Does the recipe not show up, or is it's outcome not as expected?
Nothing work ig
I try with normal clock and with the clock with customodel data 3
and its not working
i want to make the craft of all the diamond armor (with model 1) with the clock (model 3 instead of diamond)
new ItemStack(Material.CLOCK, 1, (short) 0, (byte) 2)
Why (byte) 2? How's that custom model data 3?
oops
im dumb
my bad bro
๐
And i have a question i see the short in the docs but what he mean
Is that how you specify custom model data? I thought you'd just use the ItemMeta to access this property, as you did on the recipe result above: meta.setCustomModelData(3);
No idea, I think you shouldn't be using this constructor.
That's not model data
but how i verify if clock is set to the customodeldata 3 ?
That's deprecated 1.8 shit
Pre 1.13 is too old anyways
CustomModelData is all done through ItemMeta
Create an item stack with the custom model data applied like you did on the result and then pass that to the RecipeChoice.ExactChoice constructor
so i create another item stack and i do smth like RecipeChoice.ExactChoice(nameoftheitemstack) ?
Yeah, and add the custom model data on that nameoftheitemstack
No idea tbh, as I wrote my own crafting engine from scratch, lol.
I've never used that constructor, have you checked the docs?
Insane, do you put it on github ?
i find this on a forum
It is actually, but it's a private repo. Sorry. It's not that fancy, it's just a simulated virtual workbench mapped to a double-chest GUI to support arbitrarily sized grids with a permutation generator for faster recipe resolution. It's all configurable with my expression parser in the config, but I didn't release it. Maybe I will do so one day. The project is halted currently, as I got the holographic displays as my pet project now.
Still got the url?
Its on my school pc i do it yesterday so i havent it now
Well, anyways, just use the ItemMeta-approach, as the other constructor is marked as deprecated.
Insane, do it change something to the normal way or its just easier to register new craft ?
Well, it supports recipe overloads and result pagination. And the different grid sizes, like 6x6. It also supports customized results with processor functions which can add custom item stack modifications at runtime. That was the requirement of a friend of mine I did this for, actually, xD.
Do you have a server ?
It also allows setting amounts on ingredients. Like 8 diamonds is a different item than one diamond on leggings. Special leggings, so to speak.
Or u only do it for fun
Heeeeeell no, I had two once, but never again, xD
Insane
For fun, I'm in love with logic, that's all. I never released or sold anyting, apart from three plugins in like 2017.
Are u studying something ?
Or u have a jobs ahah
https://paste.md-5.net/ogeyijezuq.java
So is this suppose to working ?
dont you need to use a space not a hashtag for empty
for that you want "III", "I I", " "
lets say I can make a menu when performing a command that is created like this java public void createCardContext(String cardName, Player player) { ContextMenuUI menu = new ContextMenuUI("What to do with '" + cardName + "'", this); menu.addAction("Remove", Material.BARRIER, (clickType) -> { CardData.removeCard(cardName); Message.sendDebug("Card '" + cardName + "' has been removed successfully!", player); }); menu.addAction("Duplicate", Material.SHULKER_SHELL, (clickType) -> { CardData.duplicateCard(cardName); Message.sendDebug("Card '" + cardName + "' has been duplicated to '" + cardName + "_copy'!", player); }); menu.addAction("Change Name", Material.NAME_TAG, (clickType) -> { String newName = KeyboardUI.getInput(); <------------------------- How do I get this input based on what item the player clicked in the keyboard menu CardData.renameCard(cardName, newName); }); menu.open(player); } How can I implement the KeyBoardUI.getInput() function of the Change Name action?
a ContextMenuUI is just an inventory and a keyBoardUI is also an inventory
waht I essentially want is the use to be able to click on an item in the keyboard inventory and use that as the input for the Change Name action, but idk how to do that on construction of the context menu
the consumer is just the method that will run when the player clicks on an option in the context menu
what is "KeyboardUI"
its an inventory, right now it is used as like a sub menu for other inventories to type stuff in, since it uses a banner pattern with the alphabet which was teh easiest way I could find to do that
oh, i usually just open an anvil menu and use the name function of it.
but in this problem it represents a class that can be used to get teh result from teh player which happens after this menu is constructed
oh
well i guess im dumb
anyways
same thing
lets say it was an anvil menu
and getInput returns the name
idk im understanding ur problem entirely correctly. but i think u can use a completablefuture for ur issue
inside KeyboardUI call a method that returns a CompletableFuture<String>, and complete that future whenever the player has finished his input
and that will allow you to run code directly when the player has finished his input
and also have access to his input
https://www.baeldung.com/java-completablefuture this is a good starter guide
should read
okay I will
thanks
from a quick scan it seems like something i half did in other places lol
t
well, time to fully do it ๐
exactly haha
why ru still using #'s
air is represented by.., well air
e.g a space
Ok, but thats not the problem when i got the item ig he hasnt the meta
how
i find why
im dumb
"meta2"

should look into ItemBuilders
so u can avoid this mess
its a plugin ?
library
this?
will allow you a pattern like this (psuedocode):
ItemStack stack = new ItemBuilder(Material.DOG_FOOD).
.name("IDK").
.lore("line1,"line2").
.etc().
.etc().
.build();
for example yes
most people eventually end up making their own
but should work
nvm its good
see how much mess that saves u?
yea , well when u have really "versatile" objects like an ItemStack. the Builder pattern can be really usefull
futures are cool and all but they're mostly multithreading stuff
guy wants a callback
fair enough you could also use a Consumer or something
i just prefer a future i guess
due to other options it has like timeout
how would you use a consumer then
well almost exactly the same
in this case
inside KeyboardUI have a method that starts the input and returns a Consumer<String>
accept the consumer when input is received
oh well yeah I guess
it would just be nesting another action inside the current one
since clicking to change the name is already being done by a consumer
yes it would
okay
I fixed it, I was super blind not realizing I did the exact same thing to make the first action in the first place lmao
how do you summon a warden doing the digging up animation with the spigot api
you can do it with regular mc commands using
/summon minecraft:warden ~ ~ ~ {Brain:{memories:{"minecraft:dig_cooldown":{ttl:1200L,value:{}}, "minecraft:is_emerging":{ttl:134L,value:{}}}}} but idk how that works with the spigot api
well one way is to just dispatch that as a command
but surely there is a better way
yeah
there would normally be the LivingEntity.setMemory method (https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/LivingEntity.html#setMemory(org.bukkit.entity.memory.MemoryKey,T))
but that requires MemoryKey as the first arg
and for some reason
those memories arent there yet (https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/memory/MemoryKey.html)
yeahhh
i cant help with that
you would want to make a new memory key, but you cant since the constructor is private
yeap
sounds like a PR to me xD
lol
I am struggling with some pretty basic inventory stuff and its getting me frustrated. I want to know when a player clicks on a item, so I am listening in a InventoryClickEvent. I am cancelling the event, but the item remains on the cursor. I saw that setCursor is deprecated, but has no mentioned replacement. I tried setCurrentItem but that removed it from the slot and didnt remove it from the cursor. Am I missing something?
I am opening a inventory after the click, would that change anything?
Delay for a tick before opening the new inventory
can you show the code you wrote in the click event?
It's likely a clientside glitch and the item is actually not on the cursor serverside
also that
new EventListener<>(RPGProject.getInstance(), InventoryClickEvent.class, (l, e) -> {
System.out.println("InventoryClickEvent");
if (this.disabled) {
l.unregister();
return;
}
if (!player.getUniqueId().equals(this.player.getUniqueId())) return;
if (e.getCurrentItem() == null || e.getCurrentItem().getItemMeta() == null) return;
if (!e.getCurrentItem().getType().equals(resourceBag.getType()) || e.getCurrentItem().getItemMeta().getCustomModelData() != RPGProject.getInstance().getConfig().getInt("static-items.resource-bag.custom-model-data")) return;
// e.setCurrentItem(null); wasnt working
e.setCancelled(true);
openResourceBag();
});
so like Task.syncDelayed(this::openResourceBag);?
I think mine might be a custom API, not sure though
Never seen that API, but running a tick delayed will do, no matter how you accomplish that
the API is RedLib
Its the same one I am using for the events
ok, thanks, I thought I was losing my mind
never had that issue before
never opened an inventory on a click before to ig
The event is called before the click actually gets processed serverside. So you're basically opening a new inventory before the click action got cancelled. You opened a new window, with a new window-id, so cancelling the click on the old window-id won't work. Something like that.
But I most definitely understand the frustration which comes with it, xD.
also, I want the player only able to drop an item they grab from an inventory, but not able to place it into their inventory. Would I use InventoryMoveItemEvent to check if it moved into another inventory, or will that call when it picks it up? Or is there a better way?
interesting
InventoryClickEvent#getAction, which basically tells you what happened. Need a few case decisions then to control what is allowed to be taken from, dropped or put into where.
ok, thanks ๐
InventoryMoveItemEvent btw does something different than what you'd imagine on first glance. The docs say:
Called when some entity or block (e.g. hopper) tries to move items directly from one inventory to another.
Shift-click-moving items is InventoryAction#MOVE_TO_OTHER_INVENTORY. Knowing at which slot it actually ended up in the other inventory again requires analysis of your own, no idea how they're still missing this feature after all of these years.
yeah, theres a lot to love and hate about spigot/bukkit
how do I convert a hex uuid to an mc int array uuid?
marh
wha
for example, c5142d60-863a-496a-baf2-9dc74f4c5214 to this
It's LSB and MSB, but split into two integers
UUID.getLeastSignificantBits() and UUID.getMostSignificantBits(), then bit shift and int limit to split
UUID uuid = UUID.randomUUID();
long msb = uuid.getMostSignificantBits(), lsb = uuid.getLeastSignificantBits();
int msb1 = (int) ((msb >> Integer.SIZE) & 0xFFFFFFFF);
int msb2 = (int) (msb & 0xFFFFFFFF);
int lsb1 = (int) ((lsb >> Integer.SIZE) & 0xFFFFFFFF);
int lsb2 = (int) (lsb & 0xFFFFFFFF);```
That might be wrong. Would need to test it. But I believe it's correct lol
The server crashes when the action bar is displayed as a loop statement
oh ok that makes sense ty
I was slightly wrong. See the edit, it's correct
Testing with the UUID you provided outputs the correct result
I want to make it say success once every second
Tell me there's a while loop in your code
YEs
Show me your code
Can I just copy-paste the code?
yes
int in = 0;
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (sender instanceof Player player) {
set.add(player);
for (int d = 0; d<10; d++) {
player.sendMessage(String.valueOf(in));
in++;
player.sendMessage("success");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return false;
}
}
why are you sleeping hte main thread
what?
Here are some links to get you started on learning Java:
- https://www.codecademy.com/learn/learn-java
- https://www.sololearn.com/learning/1068
- https://www.learnjavaonline.org/
- https://programmingbydoing.com/
- https://docs.oracle.com/javase/tutorial/java/index.html
The last one is the only official one, however some of those concepts assume that you already know a bit about programming. https://media.discordapp.net/attachments/694661573125472256/998143126373941248/6n0v4g.gif
please learn java before trying to start with spigot
for mysql, what's a good way to say "if exists - update; if doesn't - insert"?
or will "insert" just do that if i add a primary unique key to the table?
no you will still get errors with insert even with primary key
hmm
I'm not sure I always just do an exists query than send an update or insert depending on what i get back
yeah i can do that but i was wondering if it could be performance heavy
found this
top answer has 2001 upvotes so I'm assuming its pretty good
oh thanks a bunch!
?multithreading
?threading
what is it
?scheduling
read that
OK
How do I know if a sign is empty when it's placed? I tried this on SignChangeEvent
for (int i = 0; i < 4; i++) {
lines.append(event.line(i));
}
String all = lines.toString();
if (all.isEmpty()) {
return;
}```
but its not working
I'm assuming lines are ArrayList
In that case, ArrayList to String will never be empty string
no its stringbuilder
already tried it
below that code is
System.out.println(all);
and it prints nothing
boolean empty = true
For line in lines {
If(!line.isEmpty){
empty=false
break
}
}
return empty
this isnt a python lol
xd
i think im doing the same thing
when i print "all" here it prints
[08:59:06 INFO]: textcomponentimplcontent,stylestyleimplcolornull,obfuscatednotset,boldnotset,strikethroughnotset,underlinednotset,italicnotset,clickeventnull,hovereventnull,insertionnull,fontnull,childrentextcomponentimplcontent,stylestyleimplcolornull,obfuscatednotset,boldnotset,strikethroughnotset,underlinednotset,italicnotset,clickeventnull,hovereventnull,insertionnull,fontnull,childrentextcomponentimplcontent,stylestyleimplcolornull,obfuscatednotset,boldnotset,strikethroughnotset,underlinednotset,italicnotset,clickeventnull,hovereventnull,insertionnull,fontnull,childrentextcomponentimplcontent,stylestyleimplcolornull,obfuscatednotset,boldnotset,strikethroughnotset,underlinednotset,italicnotset,clickeventnull,hovereventnull,insertionnull,fontnull,children
then just print line which enters !isEmpty and see why it isn;t empty
what
its probably " " or smth
it is this
ill just replace it?
i guess
as i said, its probably space
Isn't it isBlank for things like " "?
isEmpty = check if completely empty, isBlank = check if only contains whitespace characters like " "
isEmpty just checks if the length is 0, but does not consider blank spaces
iirc ๐
^
TIL about isBlank lmao
Hey Guys, How can I write permission in plugin.yml?
If I want to add a permission as regionafk.shop.open is the below right?
permissions:
regionafk:
shop:
open:
Just add
permissions:
- regionafk.shop.open:
Search about plugin yml o ngoogle, there are examples
pretty sure its not a list
True, its probably not
so
permissions:
regionafk.shop.open:
so this would be it
The home of Spigot a high performance, no lag customized CraftBukkit Minecraft server API, and BungeeCord, the cloud server proxy.
in the BucketEmptyEvent when I use event.getItemStack() it only returns BUCKET (a empty bucket) but I need to know the data of the water bucket that was emptied, not the result
getBucket()
getBucket() gives the used bucket, but as a material
and I can't get custom model data from a material
ig
thanks, now it works
what, why
java.lang.NullPointerException: null
at java.util.Objects.requireNonNull(Unknown Source) ~[?:1.8.0_321]```
I gotta do some null checking stuff, ehhh
Java 15+ is your friend
Although in that case it doesn't change much since that method was likely called explicitly and thus has a different error message
the what
Eh, just ignore my rambling
ok
not even a month
Nah I would never leave for that long. but over a week I believe
Considering I'm here all day hehehe
Geol what would you think is the best way to organize a config.yml files if you need to allow pairs of 2 strings to then be able to store in code as a map.
Example:
String1 -> String2
Would:
strings:
string1:pair1
string2:pair2
string3:pair3
Be the simplest?
imo yaml configurations should be strictly read-only
Well then provided you didn't accidentally reinvent the array, it should be good enough
tbh with the weird things I've done lately that could be possible but lets hope not
Thanks geol.
although it depends on what you mean with "pair1", if it is a pair of strings you should store it as it's own configuration section. If it is just a string value, then it's good
streamer2:
subdomain:
split: 0.5
I believe we are on the same page here
And I just loop through each one adding the values to some data type which idk which one just yet
How will I ever store 3 things in a single variable ||classes||
How can i create a yml database in a bungeecord plugin?
yaml is a file syntax, it's not a database
generally should just use yaml for storing configuration related things as that is what it is good for
streamers:
streamer2:
subdomain: #string
split: 0.5 #double
streamer3:
subdomain: #string
split: 0.5 #double
When using fileConfig#get<something> what should I use to get a list of all streamers.
Is #getList() the best alternative here?
Or is it #getStringList
getConfigurationSection("path", false); will get u the keys
Ohhh and then each key #getList
its not a list
Oh you're right it's just a path. the entire yml file just works on paths
So then I still need to do key.value
for (String streamer : config.getSection("streamers").getKeys(false)) {
String subdomain = config.getString("streamers." + streamer + ".subdomain");
double split = config.getDouble("streamers." + streamer + ".split");
}```
You can use getKeys()
when running my command I get this output
my command code:
public class GetInfiniteWaterBucket implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
ItemStack bucket = new ItemStack(Material.WATER_BUCKET);
bucket.getItemMeta().setCustomModelData(1000000);
bucket.addEnchantment(Enchantment.ARROW_INFINITE, 0);
bucket.getItemMeta().addItemFlags(ItemFlag.HIDE_ENCHANTS);
bucket.getItemMeta().setDisplayName("Infinite Water Bucket");
bucket.getItemMeta().setLore(Collections.singletonList("This bucket was enchanted by the most powerful mages to create infinite amounts of water."));
sender.sendMessage("Item \"Infinite Water Bucket\" given.");
return true;
}
}
look in console
or smth like that, dont have an ide
getSection returns a ConfigurationSection and not a String
Yeah you're good I got it. made me realize what I did wrong
org.bukkit.command.CommandException: Unhandled exception executing command 'infinitewaterbucket' in plugin placeholdername
bruh
"placeholdername" is not my real plugin name btw
for (String streamer : config.getConfigurationSection("streamers").getKeys(false)) {
streamers.add(new Streamer(streamer, config.getDouble("streamers." + streamer + ".subdomain"), config.getDouble("streamers." + streamer + ".splitAmount")));
}
every time you `getItemMeta() you are fetching a new meta.
you need to set the itemmeta back, getItemMeta returns a copy each time
ooooooh ok
ItemMeta returns a clone, store the resulting meta, apply on that and call bucket.setItemMeta(meta);
Then add bucket to the player's inventory with player.getInventory().addItem(bucket);
oh right, forgot about adding the item lol
also the meta thing
it shouldn't throw an exception though
it returns a clone of the original each time
you have an unhandled NPE in your command handling
this is why the exception is being thrown
whats a NPE?
Null pointer exception
something is null, usually an object like plugin if you forgot to assign it a value, and are attempting to access that object while it is null but never bothered to check or better yet, initialize the object with a value ๐
?paste
hi how i can hide players name from tablist? tablist source https://paste.md-5.net/eqeheteqeb.cs
player.setPlayerListName(null)
declaration: package: org.bukkit.entity, interface: Player
?d org.bukkit.entity.Player
they should make this a command
doesnt work
Hello, does anyone know how to prevent heads from being taken from armour stands?
How can I learn how to use a API if it doesn't have any documentation? Some API's require you to initialize, others have static methods, etc.
Like what am I looking for to figure out how to use it
the forum my friend
https://github.com/CraftingStore/MinecraftPlugin/tree/master/bukkit
That specifically.
There's gotta be stuff in the code itself that can specify how it's used
ah i thought you were talking about the spigot api
No spigot api has infinite documentatiopn
does that even have an API?
that stuff is a plugin so get its instance with the pluginmanager ig
Yeah it's a plugin and it has 1 event that I need that's all
I guess pluginmanager way is the way. Lets try
so you just need to listen for that event?
just depend on the plugin in your plugin.yml, make it a maven dependency with scope set to provided and make a listener for that event like you'd do for any other event
Wait a moment
We talking 2 different things here
I know about plugin.yml and listenings for events and such
But do I need to initialize something or can I literally just listen for the event without any previous stuff?
@EventHandler
public void onDonation(DonationReceivedEvent event) {}
its a plugin so you dont need to initialize stuff ig
Oh damn
I had no clue that was even a thing
Lets give that a try then. Interesting stuff I don't even need to tell my plugin that I'm using that
wdym
what do guys think? Just made this
a rich presence? ok
Wait I'm confused fourteen I was typing it up and I noticed I was wrong
How do I tell my plugin that it's allowed to access that dependency? What you said is just add it to plugin.yml and then make the EventHandler
Is that really enough?
this yes
Ok then that's crazy but if it works not complaining
you add the appropriate imports in your class file. Now, either the dependency needs to be resent in the plugin directory or you shade it into your plugin.
I'm sad discord limits time elapsed to 23:59:59
Otherwise I would've made it 53 years
Yeah gotcha forst. Makes sense tbh
Now I'm seeing a lot of Deprecated stuff... I guess I can just ignore it
you just add the dependency
yeah you will come across deprecated stuff from time to time
If it says deprecated doesn't actually mean they added a better way to do it right?
you should avoid using such things if you can, but just because it is deprecated doesn't mean it is not usable either, just have to read the docs on why it is deprecated ๐
These docs are garbage
oh, well can't speak of other projects lmao
not surprising
now as far as listening to events that come from other plugins, you can listen for them like you would the normal events but that doesn't mean the event gets fired. Something has to implement the event to fire said event otherwise listening for it is kind of pointless ๐
Yes yes of course. I understood that. I'm just a bit surprised plugin specific events are accessible from all other plugins with pretty much no work
well that is because they extend from the events implementation of spigot
if they instead implemented their own event system, then that wouldn't really be the case
or if they instead checked who was trying to do something with a given event that is plugin specific that wouldn't be the case either
but people are too lazy to do that ๐
but in this case they want you to be able to use it
so it is a good thing then that it is easy to do so ๐
I just had a thoguht
Is events a good way to handle game states?
Like, can't you make your own events that you need fired at each moment
And listen for them
sure, it is the easiest way to notify the state of something changed
Holy sht
Why didn't I wrap my head around that before
When I first saw custom events a few weeks ago I was like wtf this is useless like I gotta create the event AND call it
I use custom events in my ServerTutorial plugin and even listen to them as well ๐
Now I see things that can be done
very useful
Yeah just had a breakthrough moment mentally
Alright gonna get back to it.
Thanks for the chat and help

also fyi, in your moment of clarity
you can use custom events to combine two events together
wait what?
do you mean call 2 events in one?
or wait for both events and send a custom event?
I'm trying to make my bungee plugin connect to database and it feels like it works, but when I send a request it says this
https://gyazo.com/746f167934baa979901184b7faa64f6b
is it binary data?
could you give more context? or code?
this is the method I send it through
public static CachedRowSet query(String query, Object... vars) {
CachedRowSet rowSet = null;
ExecutorService executor = Executors.newCachedThreadPool();
try {
Future<CachedRowSet> future = executor.submit(new Callable<CachedRowSet>() {
@Override
public CachedRowSet call() {
try {
PreparedStatement ps = prepareStatement(query, vars);
ResultSet rs = ps.executeQuery();
CachedRowSet crs = RowSetProvider.newFactory().createCachedRowSet();
crs.populate(rs);
rs.close();
ps.close();
if (crs.next()) {
return crs;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
});
if (future.get() != null) {
rowSet = future.get();
}
} catch (Exception e) {
e.printStackTrace();
}
return rowSet;
}```
I execute it like ```java
query("SELECT `ban_time` FROM `bans` WHERE `uuid` = ?", player.getUuid());```
this is also a possibility, you could use an event to call another event
but it really depends on the two events in what I was talking about though
you can listen for an event, and then if the other one you wanted to listen to as well comes after you could then combine those two events and throw a custom event that contains the data of both
however you might not be able to cancel said two events, but you could implement stuff to make that happen in a similar fashion
oh and also I think it's important, here is my connection code
private void establishConnection() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://" + configuration.getString("ip") + ":" + configuration.getString("port") + "/statistics?useSSL=false&useUnicode=true&characterEncoding=UTF-8";
String user = configuration.getString("user");
String password = configuration.getString("password");
this.connection = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}```
also, you can use one method for two events too without needing two different methods if I recall as well
one method for 2 events? like onEvents(final Event1 ev, final Event2 ev2)?
so how would you combine 2 events? i assume using some consumer or future thing
this is player's uuid
no clue why you need a cachedrowset
and you dont show how you set the params
why using a future if you're blocking on it?
so what should I use instead?
probably want to return a completablefuture
with a ResultSet, not a CachedRowSet
and please dont create a new threadpool on every invocation
Yeah I think this works, just you would have to check which event is the one that was thrown
Don't believe it works if both are thrown at the same time
been a while since I messed with the event stuff in spigot/bukkit. But yeah should experiment with stuff with the API though
be surprised in what you find out and just because no one else is doing it doesn't mean it isn't possible either ๐
I mean events cant really be thrown at the exact same time right? like it would just be on another thread or whatever
there are async events
okay so some events are thrown on their own thread and some are coming from the main thread or what?
is there somewhere I can read about this?
like I just try to handle every event as if its happening async I guess
but idk if thats the way it actually works
well its part of knowing what asynchronous means, doesn't necessarily mean another thread but in spigot asynchronous stuff does come from another thread. While technically most of the other events are synchronous, it doesn't mean 2 events can't be called one after the other, but how its called isn't really all that relevant because the server isn't going to wait for something to happen with that first event before firing the second one
so, you can have interactevent get fired at the same time blockbreak is happening
hmm
so if you combine those events in one method does it only call the method once for a random event or does it call it both times once for each event or can you set it up to have one event wait for another
or is there no way to find out
without looking at concrete implementation right now, it would call the method twice one for each event
hence why you wouldn't be able to listen to both events at the same time
yes that makes sense to me
but then it also makes less sense to have multiple events in 1 method
but it doesn't mean you can't make the code in the method diverge depending which it is though. Part of what makes OOP great sometimes when you combine it with functional programming ๐
this would be the common reason
instead of duplicating methods, you would just condense
or if you were making some custom events, it could make it easier etc
yeah and maybe you need like 1 extra check or whatever but it will reduce duplication in the end
okay I see
well thanks for your time i guess
yep, always love showing people different views on doing things mainly because I am advocate of doing things differently unlike everyone else
yes me too haha
thats why I was wondering about how it would work when you mentioned it
hello
i had a question, about server softwares that can run plugins and spigot plugins.
well
i am aware of spigot, paper and purpur as being one of the major server softwares most minecraft server seem to use.
can somebody tell me something about them?
no
is there an advantage of using one over other?
like any trade offs or any caveats or something like that?
just a general question about server softwares.
and just trying to learn more about them.
If you write a plugin for spigot it works on all of them. Not the other way around
i know that
you asked
my bad
yeah, i am aware of that, they are forks of spigot
but is paper really all that better than spigot?
as it is said?
better?
it may run better on low end servers but when you get high end it doesnt really matter
its different
it says something along the lines of aiming to be more optimised than spigot.
if it was objectively better than spigot noone would use just spigot
if you have crap server hardware then Paper may perform better.
I stick with Spigot for reliability
they have a load of async stuff
so it runs off the main thread
doesn't spigot also run things off of the main thread?
