#development
1 messages · Page 61 of 1
does that exist
never used redisbungee so no idea
Same
but its possible to do with a bukkit plugin?
well yeah since if you have a player's uuid you can just call Bukkit#getPlayer(UUID)
so wait
tho with getPlayer if the player isnt online then it would be null
so what are you trying to do exactly? get a specific player's current server?
if the player isnt on the same server as the placeholderapi instance it will return null
oh
is there a way i can make this then
if you really need it then you will have to make a placeholder that takes the player's name or uuid as an argument
how would i do that
idk google it cus ive not make a placeholder that uses a variable yet
there are a couple placeholder expansions that do that already
sooo wait
okokokk
what do i need in my plugin
to get this to work
tho im talking about specific the accepting of arguments in the placeholder, not the specific thing you want to do
so what do i need to code
what do i need to add to my plugin
like how can i do this
idk
i cant say exactly what you need to do cus ive never done it before
public String getProxyName(ProxiedPlayer player) {
JedisPool jedisPool = proxyServer.getPluginManager().getPlugin("RedisBungee").getJedisPool();
String serverName = jedisPool.getResource().get("uuid:" + player.getUniqueId().toString());
String playerUUID = player.getUniqueId().toString();
return PlaceholderAPI.setPlaceholders(playerUUID, "%proxy_name%", serverName);
this isnt working either
mind showing an example of what exactly where you want it
this placeholder to go
if your posting an image, post it to imgur or smth
header-footer:
enabled: true
header:
- <#FFFFFF>&m </#800080>
- '&5&lStormSurvival.net'
- ''
footer:
- ''
- '&5Online players: &f%online%'
- ''
- '&5Ping:&r %ping%'
- ''
- '&5l'
- ''
- 'You Are Connected Through %proxy_name%'
- ''
%proxy_name%
ahh i see
is it possible to run a class after a player does a specific event? i made an inventory click listener for when a player clicks on an item and i want it to run a different class
find a method in redis bungee that returns the proxy server's info based on the player's uuid
like i see RedisBungeeAPI#getServerFor(UUID) which returns ServerInfo but im not sure how to get the redisbungeeapi instance
how do you get the instance tho
i just said i dont know
like uh does it say in docs
grr
you dont have to run all of your inventory click code in the same class
i just did this
@EventHandler
public void onLoreBookClick(InventoryClickEvent event) {
Player p = (Player) event.getWhoClicked();
if (event.getCurrentItem().getType() == Material.WRITABLE_BOOK){
i want it to run a diff class :p
like ive got seperate classes where they have a passthrough method
how can i make such method?
like EnchantGUI#onClick(InventoryClickEvent) and ive got a map of String,GUI
create a seperate class and create that method, then at some point create an instance of that class, add it to a map somewhere like in a GUIManager class or whatever and then onclick just check the inventory to see if its the right inventory then search the map and class that method in the object
can you provide a code example if possible?
those are the classes i used for it
alright ill check it out thank you
since nobody at jetbrains cares about the javadoc issue, I'm now removing the bugged double-annotations from the generated .html files manually
tasks.register("fixJavadoc") {
description = "Fixes double javadoc annotations"
group = "documentation"
val regexDoubleAnnotation = "(?<firstLink><a .*?>.*?<\\/a>)\\s*\\k<firstLink>"
val javadocDir = File(File(File(rootProject.projectDir.absoluteFile, "build"), "docs"), "javadoc")
javadocDir.walk().forEach { file ->
if(file.name.endsWith(".html")) {
val content = file.readText()
val fixed = content.replace(regexDoubleAnnotation.toRegex(), "\${firstLink}")
file.writeText(fixed)
}
}
}
idk maybe it's useful for someone else too
why would someone at jetbrains care about it
I have put my "fixJavadoc" thing into a separate class file, however I get this warning when I try to set the property
my class looks like this
abstract class FixJavadocTask : DefaultTask() {
@get:Input
abstract val directory: Property<File>
@TaskAction
fun fixJavadoc() {
// do stuf ...
}
}
am I doing something wrong?
the = (assign) is incubating, as it says
it has nothing to do with your task itself
yeah I got no clue what that means lol
what am I suppose do to do to properly assign the directory without getting a warning?
use directory.set(...) or whatever it is
Double javadocs annotations is just because there is no way to tell if it is a return annotation or a method annotation, since Java allows both
Dokka has the same "issue" (not really an issue but sure)
What does this mean?
@Annotation
public String myMethod();
public @Annotation String myMethod();
Are the same when generating Javadocs
When you get the method annotations it'll return a list with it twice, once for the return type and once for the method
(From Dokka at least)
Because for example:
@Nullable
public String myMethod();
public @Nullable String myMethod();
The annotation is referring to the return type, but yet you can declare it on the method, the way they allow that is by combining them
It's a weird thing though, and I am not sure why they did it this way
do you know anyone i can hire to make it?
Ah I see, it makes sense ye
i dont
development is basicly to fumble through everything you try to do, eventually get something that works™️ then learn some more shit, find a new way to do something, fumble through that, go back onto the shitty code you made, rewrite half of it, do some more fumbling and eventually if you are lucky it stops looking like something a monkey on a typewriter wrote
or you can real type annotations unlike jba
tho the method ive provided basically comes down to creating a class that implements inventoryholder, creating a string variable that i can use to store an id, and on creation of a custom inventory using the bukkit method, i provide a instance of the custom inventoryholder class with an id set on its creation using its constructor.
then when you click in an inventory, i check event#getInventory#getHolder(), cast it to my custom inventoryholder type if its instanceof and then getID(). then in the menu/gui manager class i just check a map of String,GUI to see if its contained there, if so i then get the GUI object and do onClick(InventoryClickEvent) and passthrough the event to that onClick method, allowing me to split up all gui related code to their specific classes, otherwise id just have a big if or switch statement of ids and their respective code for each piece
Anyone ever wrote skin changing code based off property and signature?
I've almost got it its just being super weird with tab, either adding the name twice or not at al
and relog breaks it
hmm should I call my task "fix<originalTaskName>" or "<originalTaskName>Fix"?
is there a javadoc option to get rid of this "external link" button?
can somebody please try whether my plugin works correctly? Repository etc is mentioned in the readme: https://github.com/mfnalex/gradle-fix-javadoc-plugin
Hello is one of the gradle gooru's around?
I am trying to work with a open source plugin and I'm not familiar with gradle, why is mapOf and to not recognised (I am using IntelliJ IDEA, with the gradle extension)
is it not recognized by IJ or by gradle? IJ is dumb sometimes when it comes to that stuff
I can't import to and mapOf has imports but they don't seem to be the correct ones
actually you may be correct
I think IntelliJ is just having a crisis
the compile error isn't related to this
Google says mapOf is from Kotlin, idk if this is relevant
if you're trying to change values in your plugin.yml, the Minecraft Dev plugin for IJ auto generated this for me when I create a new plugin
processResources {
def props = [version: version]
inputs.properties props
filteringCharset 'UTF-8'
filesMatching(['plugin.yml']) {
expand props
}
}
it's a public repo I'm not personally wanting to just it's what the other developers have done all I want to do is compile it and make a fork
Hello, I have a small question, does anyone know what event or how to detect when a dispenser places a block?
Because the "BlockDispenseEvent" event on Spigot 1.9.4 does not trigger for this case.
dispensers can't place block though 
Like when a dispenser places a wither head or a pumpkin
oh right, you can do that
I just tried and it did trigger the event for the wither skeleton skulls (couldn't get the dispenser to place the pumpkin for some reason though, but the event was triggered anyways)
In Spigot 1.9.4 ?
ah, I tried on 1.20.1
and either way, the event is triggered even when the wither head isn't placed
so I don't think it'll be really useful anyways
Really weird, because for me if it's a wither or pumpkin head inside the event doesn't trigger.
Whether placed or not
maybe it changed through versions 🤷
Yeah, that's probably it
It's a real shame, because I'm developing a "FreeBuild" plugin and I wanted to avoid players being able to place blocks on the "road".
this could help if it's added, though you wouldn't be able to use it since it'd be for newer mc versions https://hub.spigotmc.org/jira/browse/SPIGOT-7468?filter=-4&jql=text ~ "dispense" order by created DESC
well I've got an idea
you could make it so Dispensers are disabled and only allow Droppers
or even make it so when someone gets/moves a dispenser in their inventory, it turns into a dropper
since they have pratically the exact same texture aside from like 4 pixels, it wouldn't really matter
ah, though if playerse would wan't to use dispensers with water in their builds, that would be problematic 🤔
At worst, players will only be able to place a block and heads or pumpkins.
then maybe you could listen to the BlockPlaceEvent, check if the item is a dispenser and get the position of the block placed, if it's on the border of the plot or facing the road, cancel the event and place a dropper instead, or nothing at all even
Yeah, this could be a good solution
Thank you very much anyway, have a nice day
help
@dawn viper Perhaps you know the answer?
As far as I understand, Minecraft automatically unloads chunks and does not allow entities to spawn, and if it does, they disappear.
I'd say check if the chunk is loaded or not, if it is then spawn the boss, otherwise keep the chunk in a variable and listen to the ChunkLoadEvent. Once the chunk loads, spawn the entity
.
im not sure if its about chunks, because if im within 60 blocks of the boss, it still spawns, but if im 1000 blocks away or in another world, it doesn't spawn.
@dawn viper
To be honest, no understand.
hm
This code does not spawn the boss after I appear in the boss's chunks.
why?
what are you doing 🤨
here, after getting the location, add an if statement to check if the chunk of the location is loaded, if it isn't, loadedChunk = location.getChunk() and return
and in the onChunkLoad method, remove the else statement and after spawning the boss, set loadedChunk to null
?
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
Chunk chunk = event.getChunk();
if (chunk.isLoaded() && chunk.equals(loadedChunk)) {
Location bossLocation = getRandomLocation(chunk.getWorld());
spawnBossMob(bossLocation);
}
loadedChunk = null;
}
put it within the if statement
otherwise it'll be set to null everytime a chunk is loaded
and therefore never spawn the boss since the loadedChunk will always be null
@EventHandler
public void onChunkLoad(ChunkLoadEvent event) {
Chunk chunk = event.getChunk();
if (chunk.isLoaded() && chunk.equals(loadedChunk)) {
Location bossLocation = getRandomLocation(chunk.getWorld());
spawnBossMob(bossLocation);
loadedChunk = null;
}
}
try it
private void spawnBossMob(Location location) {
World world = location.getWorld();
String bossType = getConfig().getString("bossOptions.bossType");
EntityType entityType = EntityType.valueOf(bossType.toUpperCase());
boss = (LivingEntity) world.spawnEntity(location, entityType);
if (!location.getChunk().isLoaded()) {
loadedChunk = location.getChunk();
return;
}
if (boss == null) {
getLogger().warning("Неверно указан тип существа в конфигурации: " + bossType);
return;
}
next code
correct?
looks good
try it
wait
put the if statement above this line
or even put it right after declaring the method
private void spawnBossMob(Location location) {
if (!location.getChunk().isLoaded()) {
loadedChunk = location.getChunk();
return;
}
World world = location.getWorld();
String bossType = getConfig().getString("bossOptions.bossType");
EntityType entityType = EntityType.valueOf(bossType.toUpperCase());
boss = (LivingEntity) world.spawnEntity(location, entityType);
if (boss == null) {
getLogger().warning("Неверно указан тип существа в конфигурации: " + bossType);
return;
}
next code
If messages should appear even if the boss hasn't spawned yet, place it right after declaring the method.
like the boss bar
new code
doesnt work.
I have no idea why it doesn't work
hm
I have a task that gets the distance between two players and then shows that distance in the ActionBar of the player.
I am sending an update to all players on the server roughly once every second.
- This seems to work fine in an async task. Is there anything problematic about running this async?
- Can I run the task once every 20 ticks and then loop through all players, or would it be better to run the task every single tick but only for 5% of players?
async is likely the better option, otherwise your server's TPS would die with high playercounts, and I think the first option (all players every 20 ticks) should be fine
do you really need to update it more than every second? maybe every half second otherwise, but every tick feels redundant and would resource hungry
though if it is the only thing happening in that thread, then it could be totally fine to be fair, but I'd still avoid that
Thank you.
Nono, as I said, roughly once a second is fine. I was just wondering whether it makes sense to update a small fraction of the players every single tick as opposed to updating everyone every 20 ticks
updating a fraction at a time seems better
probably no downsides to doing it that way
why would you update only a fraction of players though?
to stagger the load
then when will you updated the rest?
you still update everyone just not all on the same tick
yeah but it's async anyways
Yeah to spread the load but idk if it's necessary when running the task async
async doesn't necessarily mean on a separate physical core
actually idk
either way there is no downside to staggering
it's still a separate thread, so it shouldn't impact the rest of the server
I guess both can work, your choice ¯_(ツ)_/¯
i was thinking there's a chance that this thread could starve the server thread
probably not likely though
I doubt it would
what does "starving the server thread" mean?
imagine you have a hundred mc servers on the same machine
they're obviously going to all be slow
even though each is on their own separate thread
a computer can only have so many threads running at the same time
what i was thinking of is a very watered down version of that
threads can be in multiple states, if one is in a state of wanting to do work then it will obviously be on the cpu more than a thread who does not have any work to do
so if you load up one thread to do a bunch of work all at once, it might hog the cpu for a higher percentage of the time for the next few miliseconds/seconds/whatever
you'd ideally prefer it to hog the cpu for a smaller amount with breaks in between to let the main server thread catch up with a high priority in between
but all this is all excessive worrying most likely because i doubt you are going to be doing all that much stuff
I see where you are coming from. Since there is not an insane amount of performance needed to run these calculations, I suppose it would balance out, no?
I think the real question is: What happens if the async task takes longer than a server tick. Is the main server thread waiting for the async task to finish?
nah it's not
no it wouldn't be
otherwise it wouldn't really be async anymore
yeah it really isn't a worry for you, since you're mostly doing IO stuff which is just waiting more than actually doing work on the cpu
Well it could be a different thread but the server might be waiting for it in order to move to the next tick
unless you have an incredible amount of players or something, like probably way more than paper can handle
But I guess that would make it somewhat synced
another alternative to these two options is instead of processing N% of players every tick, process C players every tick
To be fair, I have no idea how complex the stuff I'm doing is / whether it would be problematic at high player counts.
What would you say?
https://paste.helpch.at/nozopugeji.java
(code is still a bit messy, I just worte that 15mins ago)
it's probably fine i really cant think of anything that would cause you issues in the first place
this way you could get the benefit of giving players a better refresh rate at low pops, while also protecting yourself from overloading yourself at high pops
(C is a constant value not related to the player count if it isn't clear)
Hardcoding that wouldn't work well for high player counts on low spec server and low player counts on beefy infrastructure tho.
it's the opposite, hardcoding would potentially protect you from lag on low spec servers and also make full use of beefy infrastructure more than using a percentage
for the low spec server, let's assume that if it tries to send the update to more than 50 players in one tick it will start having performance issues
if I set the constant to 45 it will never send more than that per tick
even if the server pop is like a crazy high number, 200 or something like that
if i use a percentage then there will always be a possibility that there are enough players on at a time that the percentage goes over 50
and for the high spec server, lets say that it can handle 80 players
i'll set my value to 60 and then if i have 50 players each one will be updated every tick
and there is no downside, players only get a faster refresh rate
but with a percentage they would not get that faster refresh rate
Fair enough, if c is configurable I guess it makes sense. 👍
However I am not sure if I have to go this deep 😄
yeah again this is really just overthinking everything
but the options are trivial to implement so it's fine lol
its a simple distance calculation for each player
minecraft probably does way more cpu intensive stuff than that every tick
I wouldn't overthink it
yeah it's just food for thought for other stuff down the line
alr
I was worrying a bit because in the code I posted above I also play around with vectors / crossproduct / dotproduct and I have no idea how resource-intensive that is 😄
you're fine, that is orders of magnitude below what you need to worry about xd
But I guess its just numbers in the end, which is something PCs naturally excel at 😄
that's all just a few cpu instructions, you'd probably rather hurt performance accessing that stuff from multiple threads due to cache misses and stuff like that
so on that level, don't try to think too much about doing work on the main thread
if you want you can run jmh on it
or you can send me the code and I'll run jmh 🥲
true
dkim rate my portfolio
it's totally finished and not still half baked
and very high quality 💯
I remember seeing it but aren't you supposed to be more professional/detailed or is that fine
I'm just in HS so I have no idea how resumes are supposed to be lol
portfolio != resume
for a resume tho you are correct
but for a portfolio you have a bit more slack to do what you want, it's basically just a platform/pedestal to show off what you've done
deep in thought
also before reading that I didn't know you did fullstack stuff
do yall pay for domains or know any free providers with janky tld's
I use dkim19375.me since first year was free
i believe ml is free
i wouldn't go for those
or at least it was until recently since i know my brother was having issues with that
ml tk and the other one
i use paid ones, and i go through cloudflare for all of em
no extra fees
if you find a good first year deal on another provider you can get it there tho, then transfer to cloudflare after a few months
yeah already used tha one in my earlier days when I didnt have a use for a domain 💀
I mean I dont really need one as of now, it would just be more convenient accessing my stuff online instead of typing out the ip
i got it when i started making plugins for ppl and didn't want to reveal my ip 🥲
wdym?
i need a better explanation for this lol
also we should probably flee to dev general
tcpshield
used to be free for unlimited domains 😔
but ig it got too popular
so its 3 domain limit
Thanks for the offer, but I suppose I'll be fine. Imma just wait til anyone complains and if they do I come here and get helpchat to fix it 🙂
domains are so cheap i dont see why i would wanna go with a free one where i have zero control
well, I don't really need one in the first place, I just have a VPS with some stuff that I'm self-hosting
a domain would be easier to remember if I'm outside my workplace
also note that you can modify hosts file to create a fake domain
but it'd only apply to that device
yeah
you can also have an ssh config file for shorthand
which has made my life so much less tedious
Nothing wrong with keeping it simple, but I personally prefer when some effort is put into the layout/design. E.g. I think it makes a lot of sense to box the content so that it is readable on wider screens.
I would work on spacing a bit (e.g. on the projects page)
And if I was to use a somewhat poorly cut out image of myself I would scale it down so that the hair / edges look clean.
You wanna keep it simple, not cheap 😉
i appreciate the review
yeah lol
since when do we allow SEGZY fellas in the helpchat cord 🥵
😳
ngl though that portfolio is nowhere near done
like i just kinda tossed the photo in because i know i want it at some point
same goes for a large portion of the text
So are you hunting jobs rn or doing your masters?
job hunting
i'm of the opinion that i can always get the masters down the line
my priority now is to finally finish my chess thingie + this portfolio, then hopefully snag a job asap
a suggestion, in my opinion it's much easier to do grad school before a job, otherwise you'll have to probably do part time both at the same time
(I'm a current graduate student)
Not sure how it's the US, but in Europe, companies don't care much about degrees. It's all about experience.
Make sure to get some kind of coding job soon, you get a lot more hireable once you have some experience as dev at an actual company under your belt.
Interview as much as you can even when you probably dont wanna work at the company. It'll make you more confident and maybe the company might even surprise you 🙂
but you also dont need a masters or phd to get a good job, unless you're going for teaching or researching
^^
definitely go for internships in the summers though
yeah i missed out big time with that
i worked as a lifeguard instead, which was fun and i made decent money but now i'm feeling the aftermath
Cache locality, synchronization, and startup time are all pretty big downsides imo lol
words
I have a question, what are the performance impacts directly using Jedis as a cache instead of using a map containing profiles used across multiple servers? Is this generally a good idea?
depends
Hey guys. I am new here. I wanted to find a discord server, where I could discuss minecraft plugin developing questions, solutions. I find it challenging to code minecraft plugins because of the lack of documentation (only javadocs, not too user friendly). Where do you guys look for help developing mc plugins?
here https://helpch.at/
they have discord server
usually you can get help in #development channel
That’s advertisement
Greetings! I have a problem with my code. The issue is that the plugin is not spawning the boss. The plugin is supposed to wait for a player to load the chunk where the boss should appear, and then the boss should spawn. However, it is not spawning. Only the BossBar and chat messages are appearing. What should I do?
whoops
does anyone know how my custom gradle @TaskAction can return the "NO-SOURCE" thingy if it has nothing to do?
Haha
I'm glad I'm not the only one struggling with writing Gradle plugins
Tbh try asking chatgpt
Even though it often hallucinates, sometimes it does tell something useful
@light pendant try this (assuming the method exists)
To achieve the "NO-SOURCE" status in your Gradle plugin tasks when they have nothing to do, you can follow these steps:
-
Define a custom task class for your plugin by extending
org.gradle.api.DefaultTaskor any other appropriate task type. -
Implement the task's
doTaskActionmethod where you specify the actual work your task should perform. -
In your
doTaskActionmethod, add logic to check whether there's any work to be done. If there's nothing to do, you can callsetDidWork(false)on your task instance to indicate that no work was performed. -
By calling
setDidWork(false), Gradle will recognize that your task had no work to do and will report it as "NO-SOURCE" when appropriate.
Here's a simplified example:
import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;
public class MyCustomTask extends DefaultTask {
@TaskAction
public void doTaskAction() {
// Add your logic to determine if there's work to be done
if (shouldDoWork()) {
// Perform your task's work here
// ...
} else {
// Indicate that no work was performed
setDidWork(false);
}
}
private boolean shouldDoWork() {
// Add your logic to determine if work is necessary
// Return true if work is needed, false otherwise
return /* your condition */;
}
}
In this example, if the shouldDoWork() method returns false, the task will be marked as "NO-SOURCE" by Gradle. If it returns true, your task will perform its work as usual.
Remember to configure your plugin's tasks appropriately in your plugin's build script and any project using your plugin.
NO-SOURCE is when a tasks's input and output don't change
Declare your inputs and outputs correctly and it'll automatically cache it
abstract class MyTasksWithOutput: DefaultTask() {
@get:OutputFile
val exampleOutputFile: RegularFileProperty = ...
@TaskAction
fun doTheThing() {
exampleOutputFile.get().asFile.writeText("hello")
}
This is an example, if the output file is not deleted (aka when you do a clean build) it'll not run the task action
Hi!
Does anyone know how to change existing value in config using https://github.com/SpongePowered/Configurate library?
root.node("maxPlayers").getInt(20);
root.node("maxPlayer").set(20);
Thx :DDD Someone didn't read error and think that was invalid syntax 😂
||root.node("maxPlayers").set(20).getInt();||
Greetings! I have a problem with my code. The issue is that the plugin is not spawning the boss. The plugin is supposed to wait for a player to load the chunk where the boss should appear, and then the boss should spawn. However, it is not spawning. Only the BossBar and chat messages are appearing. What should I do?
code: https://paste.helpch.at/opefatires.java
minecraft 1.12.2 paper
@dawn viper
Could you possibly understand what the problem is in the updated code?
thanks, I'll try that out!
as I said, that's the code from DefaultTask
Does it work tho?
unless it's some kind of different quirk
(I would be surprised if it did, considering what Matt said)
or you could just, you know
Declare your inputs and outputs correctly and it'll automatically cache it
ur not fun
I know :/
yep
well it says UP-TO-DATE and not NO-SOURCE but I'm fine with that lol
how would I declare my output file if it depends on another task that I get through @Inject in my constructor?
Make the other task an input
yeah I already have that
abstract class FixJavadoc @Inject constructor(@Input val task: Javadoc) : DefaultTask() {
That's not an input
@Input is not an input?
No because a property can't be an input, @get:Input would
hm but then how would I automatically add this to all javadocs task?
Currently I have this:
abstract class FixJavadocPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.afterEvaluate {
tasks
.withType(Javadoc::class.java)
.forEach { javadocTask ->
addFixJavadocTaskToJavadocTask(this, javadocTask)
}
childProjects.forEach { entry ->
val subproject: Project = entry.value
apply(subproject)
}
}
}
private fun addFixJavadocTaskToJavadocTask(project: Project, javadocTask: Javadoc) {
val fixJavadocTaskName = javadocTask.name + "FixDuplicatedAnnotations"
val createdTask: FixJavadoc = project.tasks.create(fixJavadocTaskName, FixJavadoc::class.java, javadocTask)
createdTask.group = "documentation"
createdTask.description = "Removes duplicated annotations created by " + javadocTask.name
createdTask.dependsOn(javadocTask)
javadocTask.finalizedBy(createdTask)
}
}
So once my plugin is added, it automatically adds a <task>FixDuplicatedAnnotations task to all existing javadoc's finalizedBy. I don't know how I'd do that any other way
What does adding the input have to do with adding it to all javadocs task?
Also use .all instead of .forEach like Emily mentioned the other day
idk, this is the first gradle plugin I ever wrote and I've only been using gradle at all since a week or so lol
What does adding the input have to do with adding it to all javadocs task?
i'm not really sure what you mean with that
what's wrong with using forEach? doesn't all expect a predicate and then just return true/false?
the reason why i suggest all over forEach is so even if a javadoc task is registered after the plugin is applied, a fix task will be registered for that newly added task too
Emily - 2023
Different all, tasks all not kotlin all
yeah I don't really understand anything, I have never used kotlin before. When I change forEach to all, I get this and I got no clue what it means
^
I have never used kotlin before
I fail to believe that 🥲 while knowing whatIterable#allwas
yeah I still don't understand what that's supposed to mean
huh?
public abstract class FixJavadoc : DefaultTask() {
@get:Input
public abstract val javaDocsTask: Property<Javadoc>
}
tasks.withType<Javadoc>().all {
val fixJavadocTaskName = name + "FixDuplicatedAnnotations"
tasks.register<FixJavadoc>(fixJavadocTaskName) {
group = "documentation"
description = "Removes duplicated annotations created by $name"
dependsOn(this@all)
finalizedBy(this@register)
javaDocsTask.set(this@all)
}
}
no i mean like
you've got to have prior experience to know what these functions are and stuff
Beauty
well the IDE tells me what it roughly is lol
true ¯_(ツ)_/¯
thanks, I'll try that - although I've never seen this @ syntax before
it just means @Input on the getter
since kotlin automatically adds the getter
not the Closure 
Well when you click it defaults to the lambda one I believe, was just pointing out the difference
I still call the tasks.withType... in my class that extends Plugin though right?
or does that really belong into the task class?
On the afterEvaluate, yes, it's outside of the class on the example I gave you
uuugh
did you mean this maybe?
tasks.withType(Javadoc::class.java).all {
// stuff
}
Don't just straight up copy and paste stuff, type it out, some stuff needs to be imported
that's easier said than done if you know nothing about kotlin
It's hard to type tasks.register and have IJ auto complete it?
well the only thing I found remotely similar takes in a normal class as parameter instead of inside the <diamondOperator>
I of course assumed the syntax would be tasks.register<TaskType>(taskName) since that's how you wrote it. Ofc I also saw there's tasks.register(taskName, Class<Task>) which seems to work
what's the meaning of this @all and @register btw?
this@all refers to "this" in the context all the "all" function
this@register refers to "this" in the context of the register function
aaah I see, thanks
so it's a bit like Classname.this in java
Similar yes, closer to labels but yeah
idk why it didn't suggest me to import the extension function here though. weird
adding the import manually has worked
(unless org.gradle.kotlin.dsl.register is the wrong one)
That is correct
hm I assume that dependsOn and finalizedBy should be the other way around though right? After all, dependsOn in register refers to the registered task I guess? I've now done it like this to avoid confusing myself
tasks.register<FixJavadoc>(name + "FixDuplicatedAnnotations") {
val fixTask = this@register
val javadocTask = this@all
group = "documentation"
description = "Removes duplicated annotations created by $name"
fixTask.dependsOn(javadocTask)
javadocTask.finalizedBy(fixTask)
fixTask.javadocTask.set(javadocTask)
}
hm nah, both versions don't run my custom task unless I run them manually
Kotlin provides you with the beautiful context swtiching so you can just type dependsOn and you do fixTask.dependsOn 
unfortunately it now doesn't run my custom task at all when I start any of the javadoc tasks
idk but somehow the "finalizedBy" isn't being applied or whatever
abstract class FixJavadocPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.afterEvaluate {
tasks.withType<Javadoc>().all {
registerFixTask(this@afterEvaluate, this@all)
}
subprojects {
tasks.withType<Javadoc>().all {
registerFixTask(this@subprojects, this@all)
}
}
}
}
private fun registerFixTask(project1: Project, javadoc: Javadoc) {
project1.tasks.register<FixJavadoc>(javadoc.name + "FixDuplicatedAnnotations") {
val fixTask = this@register
val javadocTask = javadoc
group = "documentation"
description = "Removes duplicated annotations created by $name"
fixTask.dependsOn(javadocTask)
javadocTask.finalizedBy(fixTask)
fixTask.javadocTask.set(javadocTask)
}
}
}
Seems like it doesn't like it inside the register
withType<Javadoc>().all {
val task = register<ExampleTask>("exampleTask") {
dependsOn(this@all)
}
finalizedBy(task.get())
}
This worked
Oh cool it accepts task providers 
thanks all, I got it working like this now
abstract class FixJavadocPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.afterEvaluate {
val rootProject: Project = this@afterEvaluate
tasks.withType<Javadoc>().all {
val originalJavadocTask: Javadoc = this@all
registerFixTask(rootProject, originalJavadocTask)
}
subprojects {
val subproject: Project = this@subprojects
tasks.withType<Javadoc>().all {
val originalJavadocTask: Javadoc = this@all
registerFixTask(subproject, originalJavadocTask)
}
}
}
}
private fun registerFixTask(project: Project, originalJavadocTask: Javadoc) {
val createdTask: TaskProvider<FixJavadoc> = project.tasks.register<FixJavadoc>(originalJavadocTask.name + "FixDuplicatedAnnotations") {
group = "documentation"
description = "Removes duplicated annotations created by $name"
dependsOn(originalJavadocTask)
javadocTask.set(originalJavadocTask)
}
originalJavadocTask.finalizedBy(createdTask)
}
}
If this@all is the only on in the context just use this
idk I'd rather be specific
it feels weird to me that "this" has another meaning than "this" 2 lines below
i'd much rather be able to give it a name e.g. project.afterEvaluate { rootProject ->
but that throws an error lol
Because it's Project.() -> Unit and not (Project) -> Unit
Project is the receiver not the parameter
whatever that means lol
this will be Project iirc, like in an extension function ( Project.extension() <-> Project.(), notice the similarity)
has anyone played around with minecraft's archeology update plugin development wise? Like I would like to change the loot table and customize the event, but I have trouble finding the corresponding code in javadocs
+hey there new here
ive been working to teachmyself java to develop my ow plugins the ast couple weeks and i have two plugins functioning and active to bukkit but in my latest attempt to make a new plugin for a dimension ive gotten as far as the portal ignition/break and world creation but im having alot of trouble getting the hashset of hashsets saved/retrieved via the config file, i have found some example codes that have given me mino help in trying this but im still getting nowhere seemingly after days of attempts and reserach of the jdocs i cannot see what im missing here
-im not sure if this is the channel appropriate for this tye of question but hopefully someone can be of assistance in this i'll include the line i belive should work from an example piece i found bellow
``````java
getConfig.getList("numbers").stream().filter(o -> o instanceof List).map(o -> (List) o);
```
my hashsets work to get a stream as shown via the void here (sorry had to put the link like this cus of the 10 mn exist perm) http:// ycs.canvaswrite. com/plugins/development/pastes/issue.txt
(yes this is the right channel)
I haven't used the bukkit config system in a really long time, so this may not be the best way, but try:
- when setting, convert it to a
List<List<Location>>and then tryconfig.set(listInAList) - when getting, do
(List<List<Location>>) config.getList("numbers")and convert it back to aSet<Set<Location>>
I'm not sure if regular sets are supported
you can try config.set(activePortals) and (Set<Set<Location>>) config.get("numbers") though
I would try that first
if that doesn't work, you'll probably have to convert it to a List inside of a List
hmm i'll give this a go
now this is probably an oversight on my part but when settings the listinalist i replaced that with this line but it seems to not like it assumably due to it being a hashset ```java
getConfig().set(activePortals);
wdym it doesn't like it?
is there an error?
(btw you can use https://paste.helpch.at to post your code in the future)
when i use that line the actvePortals hashset definition i put in the set highlights red and the hover error says ```
required type: String
provided: HashSet <java.util.hashset<org.bukkit.Locaion>>
ahh ok yeah that would make sense cant get to an unknown place without googlemaps first lol
probably a dumb question but how woudld i define that lol
set("active-portals", activePortals) for example
it'd have to be the same thing in getList though
ohh ok ok yeah now i get it i didnt know if there was some special way with hashsets
ok sooo idk if i put it in the wrong place or if it just got made wrong but the config upon testing that give me this```yaml
portal: !!set {}
did you use an empty set?
or did the set have values
it should have values upon creating the portal
unless i put it in the wrong place of the code
right before you do set("portal", activePortals), can you put a ```java
Bukkit.getLogger().info("Portals: " + activePortals);
it'll print out the active portals into console
just to make sure
ok i believe i just had it in the wrong place i realized it was above the hashset addition of the location for the portal im getting a shiet ton of bukkit locations with ? before them now
ok so ik this is a bit of a dingus move question but now that i can save the location sets how can i impliment the call for the locations in my code i can provide a link to the full code if that helps with this question im still learning java so im reeally not the greatest with this im mostly a javascript person
it'd be get("portal") and then you have to cast that to a Set<Set<Location>>
ex (Set<Set<Location>>) getConfig().get("portal")
with a ??
🤔
yeah heres the first few sets of like 120 sets to the one portal im testing with ```yaml
Portals: !!set
? !!set
? ==: org.bukkit.Location
world: relic
x: -329.0
y: 89.0
z: 241.0
pitch: 0.0
yaw: 0.0
: null
? ==: org.bukkit.Location
world: relic
x: -329.0
y: 88.0
z: 245.0
pitch: 0.0
yaw: 0.0
: null
? ==: org.bukkit.Location
world: relic
x: -329.0
y: 86.0
z: 247.0
pitch: 0.0
yaw: 0.0
: null
and 99+ more....
hmmm odd
see if the get("portal") works tho
oh actually apparently thats valid yaml
¯_(ツ)_/¯
At the moment I only can read:
• HelpChat Paste
• Hastebin
• Pastebin
• Hasteb.in
huh strange
oh dear theres ike 120 nulls each set variable has one
(Set<Set<Location>>) getConfig().get("portal") - is not a statement
but I don't think the : null this is not working
show code
one moment
surrounding
you have to do something with the value
in this case, you probably want to return it, so you have to change the method from returning void and return that value instead
can you elaborate?
would it be easier to just ustethe method thats in the void in the place where the void is called or would i still need more definitions to the value
I'm not sure what you mean
https://www.javatpoint.com/return-statement-in-java for more info
Return Statement in Java with java tutorial, features, history, variables, object, programs, operators, oops concept, array, string, map, math, methods, examples etc.
anyways I'm gonna go sleep now, gn
m brain hurts from trying to understand this lol im off to the sleep now too better luck tomorrow hopefully lol thanks for the help
Hey ! I was wondering how can I find out a player's client brand
I googled a lot but no sources for newer versions
There is a packet sent for that, go to https://wiki.vg/Protocol and search for Brand
let's suppose I have a class with a Map<String,T> and this class implements Iterable<Constant<T>> where Constant is just a class that has a name() and a value().
Which would be better, returning a new Iterator() { ... } or just return a stream().map(...).iterator() of the underlying map? In this example, I'm using a new Iterator for the Iterator and the mapped stream for the spliterator, I wonder which is smarter/better?
@NotNull
@Override
public Iterator<Constant<T>> iterator() {
return new Iterator<Constant<T>>() {
private final Iterator<Map.Entry<String, T>> iterator = elements.entrySet().iterator();
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Constant<T> next() {
final Map.Entry<String, T> entry = iterator.next();
return Constant.<T>of(entry.getKey(), entry.getValue());
}
};
}
@Override
public Spliterator<Constant<T>> spliterator() {
return elements.entrySet().stream().map(entry -> Constant.<T>of(entry.getKey(), entry.getValue())).spliterator();
}
smarter/better for maintainability? probably a stream, smarter/better for performance or memory footprint? it likely doesn't matter that much with a single operation honestly, but pedantically speaking a simple anonymous Iterator (and the default impl for spliterator())
hmmm I guess I'll roll a dice lol
genius
internal fuzzing lmao
yeah I ended up doing that
private static boolean amIFeelingFunnyToday() {
return ThreadLocalRandom.current().nextBoolean();
}
public Stream<Constant<T>> stream() {
return elements.entrySet().stream().map(entry -> Constant.<T>of(entry.getKey(), entry.getValue()));
}
@NotNull
@Override
public Iterator<Constant<T>> iterator() {
if(amIFeelingFunnyToday()) {
return new Iterator<Constant<T>>() {
private final Iterator<Map.Entry<String, T>> iterator = elements.entrySet().iterator();
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Constant<T> next() {
Map.Entry<String, T> entry = iterator.next();
return Constant.of(entry.getKey(), entry.getValue());
}
};
} else {
return stream().iterator();
}
}
Very nice
Hello, I'm a front end developer and a web developer that can create WordPress websites. Please let me know if you have any projects.
Some of my website which i have made on the month of august
-http://www.sylvanlearning.com/
-http://leasequit.com/
-http://www.christiesrealestate.com/
-http://www.araujoestate.com
-http://iproperty.com.au/
#1147713998612091010 @grizzled pulsar
hello i wanted to ask if someone knows about itemsadder plugib addons because i need a rank tag addon for you 1.20.1 who nice if i could get help?
Hey, so I'm using HikariCP for SQL database in my plugin, I just want to know how can I improve the implementation for using HikariCP, this is my current code right now https://paste.helpch.at/uyeyumopir.java and I got some people reporting that it has issues, it's saying that connection is closed or an error message that says "Apparent connection leak detected".
connection leak would mean you're using the datasource incorrectly. Your setup here looks okay I guess
public Connection getConnection() throws SQLException {
if (this.mysql) {
return this.dataSource.getConnection();
}
if (this.connection == null || this.connection.isClosed()) {
this.connection = this.dataSource.getConnection();
}
return this.connection;
}
```This is how I get the Connection object everytime I want to modify the database.
and how do you use that method?
also why not always use return this.dataSource.getConnection()
public void buildStatement(String query, QueryConsumer<PreparedStatement> consumer, Consumer<SQLException> onFailure) {
try (Connection connection = this.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(query)) {
consumer.accept(preparedStatement);
} catch (SQLException ex) {
onFailure.accept(ex);
}
}
```Something like this.
I just thought if I'm using SQLite, there is a chance that the connection is closed and I need to reopen the connection.
Alright, I will try to do exactly like you said and I'll let you know if there are any issues.
I am working on a documentation style website, and I need a way to spice up the text. I have these large sections of text that I need to make easier to read. Here is an example, what do you guys think I could do to make it look better?
Honestly, looks fine to me, but I do know a lot of people will probably just skim through it.
You could add a Podcast like recording at the top which pretty much covers the text.
can anyone tell me why bed.getWorld() is non resolvable in this case?
Location bed = player.getBedSpawnLocation();
player.teleport(new player.getWorld(),bed.getX(),bed.getY(),bed.getZ());
why do you have new in there? 🤔
without it it didnt like any of the values
do you just want to teleport the player to the bed location?
yeah cuz that method doesn't exist like that
just player.teleport(bed)
teleport takes a Location
np
Can't construct a java object for tag:yaml.org,2002:Config; exception=Class not found: Config
https://cdn.discordapp.com/attachments/1060742546130735124/1149173428096614491/image.png
https://cdn.discordapp.com/attachments/1060742546130735124/1149173428377624637/image.png
https://cdn.discordapp.com/attachments/1060742546130735124/1149173428633481308/image.png
What the heck is goin on?
(SnakYML)
Error is on the loadAs method!
what is this goofy mc font
ok so i did some looking and it looks like its cuz snakeyaml sucks
https://github.com/spariev/snakeyaml/blob/master/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java#L624C1-L624C36 is using Class.forName so u prob cant fix it
make a pr that lets u specify a class loader
actually nvm
looks like you can use a CustomClassLoaderConstructor
Is there a simple way to simplify this?
public List<String> getKingdomNames(){
List<String> kingdomsList = new ArrayList<>();
for (Kingdoms kingdomLoop : kingdoms)
kingdomsList.add(kingdomLoop.getKingdomName().toLowerCase());
return kingdomsList;
}```
I don't think using a for loop is so smart for this
first thing id say is to simplify the names, so maybe something like this:
public List<String> getKingdomNames(){
List<String> kingdomNames = new ArrayList<>();
for (Kingdoms kingdom : kingdoms)
kingdomsNames.add(kingdom.getKingdomName().toLowerCase());
return kingdomsNames;
}
then we could probably rename Kindgoms to Kindgom, getKindomName() to getName since the Kindgom is kinda redundant
public List<String> getKingdomNames(){
List<String> kingdomNames = new ArrayList<>();
for (Kingdom kingdom : kingdoms)
kingdomsNames.add(kingdom.getName().toLowerCase());
return kingdomsNames;
}
then, maybe you could replace it with the streams API to make it shorter and arguably more readable
public List<String> getKingdomNames(){
return kindoms.stream()
.map(kingdom -> kingdom.getName())
.collect(Collectors.toList()); // or just `.toList()` if being immutable is ok and you're running Java 16+
}
i do think that you should leave getting the names of all the kindoms to the caller though since they should really be choosing what to do with all the kindoms
Yes I know, but it isn't really an API tho.
But thank you!
And for the advice above too
Tried that too, same error.
Is there a workaround if some sort?
is there something like this? PlaceholderAPI.replacePlaceholders(player, placeholder)
.setPlaceholder
when you do object.getClass() does that return a singleton varient that you can use in a map as a key for example?
yes
I am looking for a code obfuscator. What should I use?
You shouldn't!
Especially not if you're posting a Minecraft plugin, etc. Spigot disallows obfuscation (for good reason!)
they do allow them
they are allowed for premium plugins too?
Hangar, tho
straight up disallowed
but yeah, it's stupid anyway, no-one's gonna want to steal your stinky code 
wait really? i swear they disallowed premium obfuscation
ah here we go
yeah it's severely limited
allowed nonetheless, which tbh it only makes it less worth it lol
well what if I am posting it on mcmarket
Buenas!
English
I'm using allatori - only bought it because it's tax deductible anyway though. It's pretty pointless, especially since DRM is only partly allowed on spigotmc
actually, premium plugins are allowed "more obfuscation" than free ones
e.g. string encryption is completely forbidden for free ones
how is it pointless?
Every problem that obfuscation claims to solve, it actually doesn’t
and introduces more problems elsewhere at a cost
obfuscation is a pain in the arse cus when trying to diagnose issues you dont have a clue whats actually going wrong
I like when I get error at a.b.c.A(A.java:54) 😋
so helpful
or iiiiiiiii.iiiiiiiiiii.iiiiiiiiiiii.IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
I wonder whether the developers can actually reverse the stacktrace from the obfuscated form into the original
If it's just peoguard then yeah
Proguard
well obfuscation is not pointless per se, ofc it takes more effort to reverse engineer it if it's heavily obfuscated. But since spigot doesn't even allow proper DRM systems, nobody stops you from simply leaking the .jar elsewhere
so people don't even care if your code is obfuscated, they can just upload it to <illegal website> and that's it
uh yea, thats going to be a issue lol
I am actually looking to upload the premium resource on mcmarket as it supports more than just paypal and stripe and I think having obfuscation to make it difficult for the code to be read and DRM system implemented in the code to atleast be able to catch users who leaked the plugin, should be good for protection
You'd be better off just selling support. That way you don't need to care if it's obfuscated or need to do any DRM, you can just check if they've purchased it when giving them support.
It's a much better business model, much less consumer hostile. Most people don't want to put up with DRM and shit when there are tons of awesome plugins that are free/open-source/just pay for support.
yeah that's how I also do it for all plugins except two. All others are open source but I'm still using allatori on them so idiots can't figure out how the discord verification works so I can see whether someone bought the plugin or not, lol
heya, for some reason only one person that is using my plugin out of thousands of users is recieving an issue where they cannot read a serialized object.
I'm pretty sure you can use allatori for free on plugins
Since plugins don't have print statemebts
But I only used it back when I thought everyone used obfuscation
So it's been like 2 years
So it mightve changed
actually, now that I think about it, that is definitely a better way to sell
https://imgur.com/AnN41jM
how to fix?
When I replace Player with OfflinePlayer, the error disappears
And I just need Player, otherwise I won't be able to get the DisplayName
well if you have OfflinePlayer you can try to convert it to a Player, if he's online
Please tell me how to do it
that if statement for display name equals name is redundant btw
sure, ofc you can. but you have to disable many settings
oh really?
I don't remember being many limitations (if any) before when I used it, but again it was a really long time ago so idk 🥲
my memory's probably lying to me
well for example you must not use "illegal" names, e.g. if you set the renaming mode to compact, it'll use class names like aa, ab, ac, etc.
Well if you do have a bunch of classes, it'll some time reach "if" which is a keyword and hence not an illegal class name anymore lol
there's this one resource staff who is always very picky over such things and I had to change my obf settings many times because of tiny things like this
wait are you talking about allatori or spigot
another thing is, the synthetize-fields and methods options must both be disabled, no clue why they don't allow it
I meant allatori in general
I'm not talking about spigotmc rules
oh ok
bc u said this
so
¯_(ツ)_/¯
whats that?
it marks fields or methods as "synthetic" which means they don't have any associated source (generated methods), like e.g. I think valueOf on enums - some decompilers will then only show an empty file
ohh interesting
yeah e.g. here, you don't see valueOf() because it's a synthetic method
oh wait
it is visible there because recaf is not stupid
some decompilers would have hidden it
yeah recaf has a setting to show them. hence I also don*'t understand why spigotmc doesn't allow this setting lol
yeah but they could also just click "Show synthetics" in their settings lol
¯_(ツ)_/¯
but yeah no clue, obfuscation is mostly pointless anyway
or rather than an obfuscator, just write ur plugin in kotlin
only mention of the demo is the "Download" button
it adds System.out.printlns, and you're simply not allowed to make money with it
adds or modifies?
yes lol the decompiled code looks like 11 year old hacker-man wrote it
i don't know that
oh ok
Unless you decompile it with a Kotlin decompiler lol
IIRC it adds its own "==== ALLATORI DEMO VERSION =====" system.out's or something but only right above or below your own System.outs
so if you didn't use any System.out, you'd be fine
r there even any?
even without a kotlin decompiler it's not that unreadable
for ex if you're trying to bypass some DRM
its fine if ppl can read it but they can easily modify it
or just sell support and have an open source unobfuscated plugin with no DRM 😌
oooh it is. lemme you show a tiny thing
no I mean like if you want to find DRM
I don't think it'd be too difficult
oh yeah sure. just wanted to say, decompiled kotlin looks like shit
here's my tiny gradle plugin's main class
actual code: https://paste.jeff-media.com/?ab284a6fac094677#GMcNF56YHkgduG19xtJbWagZs72WG4dFZQTAmyUJSuZy
decompiled: https://paste.jeff-media.com/?1af57f3e7960fc5a#5EKsekKYJacm2YV3DKLgnFZMKLfMgxP16j4GGmqqLbLN
because ur decompiling it in a diff lang 🤯
its like the java to kotlin converter but a little worse
https://www.spigotmc.org/threads/allatori-obfuscator.229831/#post-2336879
this guy spending a thousand dollars for obfuscators 💀
just use proguard or smth smh
Don't remember which one IJ uses but it's pretty good
wait what
IJ has a kotlin decompiler?
it always just shows /* compiled code */ for me when decompiling a kotlin file
fernflower or smth i think
yeah fernflower is definitely better than CFR on kotlin but still pretty shit
Some, it is still kinda funky
ah
do you read the bytecode directly or what?
Yes, who needs books when you can just read bytecode
no I meant that if you're looking for DRM inside the code, it's not that difficult
what code?
kotlin code
so, decompiled
yea
but java decompiler
right
left

Poor dkim 😔
dkim's new profile pic?
yikes, been a long time since I've seen putty
yeah idk I'm used to it and it integrates nicely into winscp
on mac I just use the builtin terminal
no iTerm2????
what a minimalist
been using winscp with putty for several years now
does the job, idk
Same, works just fine
any suggestion on how I could improve my project layout? https://github.com/mfnalex/cesspool
I'm annoyed that I have to repeat the same steps in every NMS module's build.gradle.kts file (remap plugin, spigot version, remap-plugin task spigot version) but unfortunately, I cannot declare global functions that are accessible from submodules, nor can I pass "variables" to buildSrc scripts
I'd also love to somehow get rid of the redundancy of writing the same code over and over again for each NMS module (I'm gonna support 1.16_R1, R_2, R_3, and every 1.17+ version) and there'll be alot more methods in NMSHandler
I thought about writing a script to just copy/paste the new method to all other modules that use mojang maps but that seems like a terrible solution
I also cannot use paperweight-userdev as that would force me to use gradle toolchains which I can't, as they don't allow compiling for an older -source/-target version, which I have to to support 1.17 and 1.16
1.17 and 1.16.5 (paper) work fine with java 17
yes but many of my users are still using java 8 and they're gonna complain if only one plugin requires java 17
well they should update then
yes I know, but that doesn't answer my question. it's not my job to tell my customers what to use but deliver what they want, lol
it is up to you to support whatever you want
I don't think it looks "too flat" but I think the colors are not very well chosen.
E.g. the sidebar, it's dark blue and the text is also dark blue / purple, that's a bad contrast.
and for the main view (the big table), I'd use a slightly alternating color background for the rows
with "slightly alternating color background for the rows" I mean sth like this
yes, that still doesn't answer my question. being forced to use toolchains isn't the only reason why I don't wanna use paperweight. Another reason is that I don't wanna give up spigot compatibility and paper-userdev inevitibely comes with paper-api
Alright. What colours do you suggest for the sidebar
oooh I'm very bad at choosing colors. I always use a "matching color" generator, e.g. this one https://coolors.co/
You can basically enter a number (hex color) and then it gives you like 5 different colors for a matching palette of colors
Doesn’t mean you have to do something that makes it incompatible
I have a bit of a problem, my plugin requires the use of custom bounding boxes (AABB) but I need to be able to rotate the yaw. I have no clue how to do this and have tried stuff like this:
public AABB rotateAABB(AABB originalAABB, double angle) {
double radians = Math.toRadians(angle);
double sinYaw = Math.sin(radians);
double cosYaw = Math.cos(radians);
originalAABB.setMinX(cosYaw * originalAABB.minX - sinYaw * originalAABB.minZ);
originalAABB.setMaxX(cosYaw * originalAABB.maxX - sinYaw * originalAABB.maxZ);
originalAABB.setMinZ(sinYaw * originalAABB.minX + cosYaw * originalAABB.minZ);
originalAABB.setMaxZ(sinYaw * originalAABB.maxX + cosYaw * originalAABB.maxZ);
return originalAABB;
}
I also have some other code but that makes it turn really weird (like when its perfectly 90 or 180 then its good but if its not then the bounding box becomes HUGE)
AABB is your custom class? the question is, on which point do you wanna rotate it around on? the center, one of the corner locations, or some arbitrary location?
sounds stupid but ChatGPT is pretty good on solving these kinda math questions if you explain the problem very detailled lol
We're using userdev and have compatible plugins on SpigotMC, don't see an issue tbh
is there a reason you're using websockets as opposed to just sockets o.o
ofc it might work if you don't use any paper specific stuff
I would however rather just use spigot's api in the first place. I still don't understand why all the paper contributors are so afraid of contributing upstream
90% of paper contributors are like "huuuh spigot is so shit. I have easy fix. Lemme contribute it to paper instead of contributong it to spigot lol"
i think its more because to contribute to spigot you have to give out personal information
the CLA
yeah but MD5 somehow has to know that you don't just copy/paste other people's code
imagine how much trouble he'd be into if he'd just accept "any random code" and then later on someone else claims "duuude that's my code"
i dont think alot of people would be willing to give up stuff like their full address to contribute to spigot
yeah you're right, although I never understood it
when you got the options of contrib to spigot and risk getting your identity stolen or contrib to paper where you give up no information and your gunna end up using anyways, i think the option is clear
that information will only visible to md_5, and even IF it would be public, what are you gonna lose? worst thing that can happen is that someone thinks "lol Alexander Majka @ Jünkerstraße 17 in 48165 Münster's pull request is really bad lol"
(above mentioned details are mine, just for the records @ mods)
I do understand that people don't wanna give away their draits for whatever reasons. But spigot has to be sure that the code contributed has to be linked to someone
I mean, how else would spigotmc be sure to not accept propriatey code or sth
I understand both sides. Imagine you accept a pull request for "feature XYZ" and 1 year later you get sued because you're usinh ABC's company's code and all you can say is "well someone PRed it"
idk if this ever happened to paperMC but it MIGHT happen anytime
(it probably never happened and it probably will not ever happen, but if it happens, PaperMC is fucked and has to pay lawyers etc)
and yeah that's why Spigot requires signing the CLA
I'm definitely not an md_5 ranboy but he does things correctly in legal terms
imagine you'd be running like the "base version" of every normal server software mod - ALFTER all these CLA stuff happened. Ofc you wanna be on the safe side and only accept PRs of people you know you can trust
also, just for the record: I'm definitely not an md5 simp, he does many shitty decisions. but the CLA stuff is not one of them imho
Would def. recommend working on your spacements, not following some design rules
Also, the gradient in buttons seems quite useless? And quite out of the theme.
A color pallete could help with those color issues
regarding the "flat" thing, I mean, modern UIs are mostly flat? And it's the trend now sooo
lol
Paper brings as patches some fabric mods optimisations (obviously if the license allows it, the license is compatible, and with the appropriate copyright notice), so there's that for code ownership, and something tells me md5 wouldn't be really keen to have an entire chunk system rewrite, light engine rewrite, redstone engine rewrites, data converter rewrite, changes in the networking stack, etc etc
also the whole project not being gatekept by a single person is something I see as a positive, and spigot not releasing snapshots/pre/RCs is something we (I personally and we at downstream) see as a very major negative as it only delays and largely impacts the updating process during Minecraft updates
I would never in my entire life, even if I was paid, give any of my informations to md_5, legit the most untrust worthy person in the whole community, biggest ego I have seen and many other things
Also, what are you gonna lose?, uhm idk, PRIVACY?
I can probably find at least 50 reasons why putting your god damn details publicly online is bad lol
Also it's not like no-one at Paper wants to MR changes to Spigot, even as of very recently, but those have a different "purpose" as to what we tend to do in Paper
I am pretty sure most people contributing to paper would contribute to spigot if it wasn't ran by md_5 and solely him tbh lol
it's another Forge & NeoForge fiasco
difference is, instead of lex, we have md_5
and instead of a whole team, you have md_5 lol
Tbh I think that the main reason people contribute to paper is that working with md5 is well, suboptimal to put it mildly
Also, the CLA
But like, who uses spigot in 1.20.x?
people who don't know better
huh I don't remember having started a discussion about spigot vs paper but sure, I'm happy to contribute. gimme a few minutes until I had my morning coffee and I'll tell you some pros and cons too
with morning coffee, I mean beer btw as this is an annoying day
of course paper adds many new API additions, which is nice. At the same time, they seem to have a very strict internal rule like "be sure not to contribute it to spigotMC too".
I remember having PRed the Translatable interface to bukkit and craftbukkit and a few minutes after I did so, some paper fanboy started a discussion on stash, linking to the already existing paper patches for this (which I didn't know about, btw) which leads me to the next conclusion:
Once something got added to paper, they claim "ownership" over that for the general idea of having invented this, even for trivial things like the above mentioned Translatable interface. This is ofc a pain in the ass (in the bad way, not the good way) as people will have to decide to either contribute to spigot, which paper will then accept, or PR it to paper, knowing that if spigot adds it too, paper's gonna complain.
Paper's website isn't even GDPR-compliant. There's no data privacy policy and not even a proper site imprint - the website is basically ran by "unknown" and that's a huge "yikes" if you're living in the EU. Spigot also does not have a proper data privacy policy but it's clearly visible from their site notice that it's run by an australian company (SpigotMC PTY LTD) so we at least know, they don't have to care about GDPR laws.
ANother thing you mentioned is "whole project being gatekept by a single person" yeah that is true, however MD listens to suggestions and sometimes also adds stuff he himself wouldn't do, if there wouldn't be many people who are in favor of adding said thing. Exampe is the BuildTools GUI we recently wrote. I don't think that paper does it any better - I made a pull request to fix the broken javadocs, which have been an issue for YEARS - electronicboy complained about "adding third-party repos is a nogo", so I got my gradle plugin approved and it's now officially part of the gradle plugin portal. I mentioned that in the github pull request and since then, nothing has ever happened.
I'm also banned on paper's discord (final reason was because I sent a soundcloud link that staff thought was inappropriate, which I only partly understand) however this basically rules me out of every possible contribution to paper besides opening pull requests that then get silently ignored. For example sending a song by <random rapper> where he talks about <fucking X amount of bitches> is fine but if it's a song you made yourself, then that's an insta-ban? Does one have to be popular to rap about stupid things? Seems so, kinda.
I do agree that md can be annoying at times (e.g. see my discussion with him about PlayerEditBookEvent), but at least he doesn't arbitrarily ban people.
Paper also accepts code (if they do) from ANYONE without any license, meaning they could be taken down anytime if someone'd be to commit stuff that contained other people's copyrighted code. That's why Spigot uses the CLA and I got no clue why so many people are afraid of it. I mean, if you don't wanna prove that you are yourself, then maybe there's some underlying issues first that need to get fixed? idk, I'm a lawyer, not a psychiatrist.
All that being sad, I think the paper project is a great thing, if only they wouldn't always go their own way and would contribute upstream more.
talking about the GDPR issue, I have mentioned this to lynxplay and other paper staff many times, they always said "oh yeah I'll note that, thanks" and then nothing happens. I think I already reported this the first time 2 years ago (reported to staff ofc, not to the data privacy office lol)
Their new way of differentiating between "paper plugins" and "Bukkit plugins" is also, imho, a very bad idea. It leads to sooo many issues. For example, the paper plugin.yml is missing basic features such as the library-loader (added in 1.16.5), and registering commands (unless this has changed meanwhile)
they basically give a fuck about spigot compatibility while they still happily fetch upstream whenever they need to
ok I'm done now. I don't hate on paper, just wanted to clarify that nothing's perfect there, either
Contributing to spigot is a pain in the ass and half the time your PR stays open for ages and never gets merged because it changes too much or no one cares
It's a lost cause
yes that is true but unfortunately the same happens on paper
for spigot, I know that I can bug md_5 on discord to merge it NOW, usually he then does it
for paper, idk I already got banned there for sending a soundcloud link
my pull request on paper is open for > 1 week now and I have eleminited the only criteria that electronicboy complained about https://github.com/PaperMC/Paper/pull/9682
but sure, similar things happen on spigotmc too
A whole week?
There are PRs open on spigot for years lol
it's not like that's a critical fix
lol I think it is, the javadoc's been broken for no reason for years now
this plugin fixes it with only adding one line to the main build.gradle file
where everything is @NotNull @Notnull ?
"broken", it's just aesthetic
i wouldnt even say its broken
it IS broken, because it suggests that every method etc is annotated twice with that annotation, which obviously it isnt
it doesnt though
it suggests that type usage and the method are both annotated
which they both are
because @org.jetbrains.annotations.NotNull has the TYPE_USE and METHOD targets for backwards compatibility
it corresponds to what reflections will give you
yes, I know the origin of this issue, and ideally it'd get fixed in javadoc itself
yeah but is it really wrong?
no, it doesn't mention anything about why this annotation appears twice
yes
@NotNull String giveRandomString();
this should have ONE notnull annotation
not two or 7
you're wrong there, in the reflection model, the annotation is on both the annotated type and the annotated element
I'm, not wrong there, I'm simply looking at the javcadocs and not at what reflection on the annotation tells me
That technically is 2 annotations, one for the return type and one for the method
well the bytecode has the annotation on the type usage and method
the javadocs aren't the source code
do you really nt consider this to be a bug? Do you think this makes any sense?
and while I think it would make sense to deduplicate the annotation in the javadoc because it doesn't provide any value, it's far from "broken"
its just giving you the annotations in a different context, its not wrong
yeah we're going in circles. This tiny javadoc issue wasn't the only thing I mentioned in my huge "paper vs spigot" message
which are the contexts? "Once" and "Then again, in the next line lol"
yeah you also pretended like a CLA prevents someone from copying in code they aren't allowed to use somehow lol
ofc it does not prevent that
but the maintainer can then go to "whichever authority is presecuting the copyright claim" to say "well it wasn't me, it was this person: [name], [street], [city], [country] and they assured me it's their own code
Also you should try to upstream some of paper's changes to spigot and see how it goes :)
the CLA is nothing more than a promise to the maintainer "I indeed wrote this myself and didn't copy/paste it from somewhere else"
you don't need a CLA for that
I already know how this goes. I added a Translatable interface, which paper didn't have back at the time, but somehow ONE of the methods I added was pretty similar to paper's version (which makes sense, there only is one way to get an Items TranslatableKey lol) and they went nuts
So it isn't paper not wanting to upstream then huh
fact is spigot is more of a painful hurdle than a contribution to the minecraft community for years
yes, I agree that it's annoying to contribute to spigot too
also
it's run by an australian company (SpigotMC PTY LTD) so we at least know, they don't have to care about GDPR laws.
this is wrong, just because the company isn't from the EU doesn't mean they can provide services to users based in the EU without having to respect their rights
I love this discussion
you're right, but we also know that there's no way to prosecute an australian company for violating GDPR stuff, unless they actually do business in the EU
spigot itself doesn't do any business stuff except accepting donations and getting sponsered by a few companies like aternos
(at least from my knowledge)
I also didn't mean to start any spigot vs paper war. both projects have their flaws, obviously
btw does anyone know the process of getting an ecloud extension "verified"?
do I have to ping anyone for that or sth
it just says "If you're a verified dev, your version will be approved and is available directly.
If you aren't a verified dev, you have to wait until a moderator approves the update."
am I missing something there?
I'd like people be able to just do /papi ecloud download Replace
which currently isn't possible because it's not verified
I also don't know whether i'm a "verified dev" or not
I only know that I got an account to upload stuff to ecloud, but whatever I upload there isn't "verified"
1st and 3rd paragraphs are just plain wrong
That's not the reason why you're banned, sending music isn't rulebreaking, we don't arbitrarily ban people either
With over 200 PRs open, ones have to take priority over others, that's like very low prio, and this is the structure of many large projects too, outside of Minecraft, outside of Java
We don't "just accept code" either, I can't explain the whole process right here right now but we definitely don't do "oh look, a pr merge"
but it's fine, who cares
@ funnycube or @ piggypiglet probably
For example sending a song by <random rapper> where he talks about <fucking X amount of bitches> is fine
is that to do with his album
well discussing the reason of why I got banned isn't what I intented to do here. Let's ignore that part.
You say "1st and 3rd paragraphs are just plain wrong". You're talking about the fact that paper contributors, rarely, if ever, send the same PR to spigot - and if it does happen that Spigot gets a feature that Paper already had, people are starting to harass you in the stash comments. A good example is my Translatable pull request. Unfortunately I cannot find it right now because spigot's stash / Atlassian Bitbucket is a fucking pain to use lmao.
I ofc understand that with 200 open PR, decisions have to be made which one to merge first etc, but it'd at least be nice to get a reply like "Yes, this looks good/bad, we'll merge if it doesn't cause issues / or not". Neither happened.
And I can only repeat myself, both spigot and paper have their issues regarding many things. This was just a tiny breakdown of things I was angry about an hour ago
does that really happen tho? it isn't uncommon for upstream to add (missing) events or interfaces that paper might have already had for a bit, and I never see anyone say anything other than maybe causing confusion in our dev help channel, all that happens on our side is we simply deprecate the one that has least useful methods
it's a bit annoying because I went through the hassle of getting my fix-javadoc-plugin approved for the gradle plugin portal, knowing that paperMC was the only repository that required it. Everywhere else where I suggested it, they just were fine with adding my repo to the plugin repositories. So I thought, sure, if that's the only issue, I'll upload it to the plugin portal. After I've done so, I got no reply whatsoever, it kinda feels like people don't even care and would rather keep their broken javadocs instead of getting it fixed, fixed by someone who they banned
that happened a lot of times, e.g. check out ADvancedDisplay and the issues it had caused back then
"broken" javadoc
the javadocs are broken
they are finely functional
if you @NotNull a parameter and the javadocs claim you @NotNull'ed it twice, then the javadocs are broken, easy as that
we must have very different definitions of the word broken then
unusable
they work just fine
thats kinda like discord sending your message 30 times when your internet craps out, its not broken but its dumb!
maybe that's better than broken?
they're just making sure that people know it's definitely not null 
Javadocs are there to "describe that source code and what it does" and currently it describes literally every method parameter with being annotated with the same annotation twice, which is wrong, and hence the javadocs don'T do what they're supposed to do, and hence they are broken
ofc they are still "Usable"
you can also run a marathon if you got cancer, doesn't mean that your body is healthy
they are there not to describe the source code
didn't they say that it's because the annotation is on the field and return value or smth
so there should be 2, it wouldn't be broken, but it's not pretty
my bad. they are there to describe the declared classes, methods and fields
you know what I mean
functional??
proves you enough you aren't broken, if anything
we know that you repeat that over and over again but it doesn't make it right
If a parameter is annotated with exactly one annotation, the javadocs should show exactly one annoattion.
also I don't know why you pretend like this is a paper issue
it's not a paper issue at all
the bytecode is annotated twice though
(according to someone here, I don't remember who)
it's an issue caused by javadoc itself
the parameter is annotated and the parameter type is annotated
which is correct
it does make sense in the bytecode, yes, but it does not make ANY sense in the generated html file
then it's a cosmetic issue
ig?
yes
well more or less
it's definitely not broken
that's a nice word for it
the javadocs don't mention whether the parameter or the parameter's type is annotated
if a plugin of yours sends a message twice, then it's broken, isn't it?
which is definitely an issue that must be fixed on "javadoc.exe" itself
or however it's called
then this PR won't fox it either
that is true, it's a workaround
Easy, use dokka
yeah, a workaround to get javadocs that look like what they should have looked like in the first place
imho it's definitely the wrong approach to address this issue
does dokka work for java?
They display it correctly mate?
Obviously
no, they don't
Yes, they do
@Contract(pure = true, value = "_, _ -> new")
@NotNull
public static List<@NotNull String> apply(@NotNull List<@NotNull String> strings, @Nullable OfflinePlayer player) {
// ...
}
They technically display it correctly, because it's generated from the bytecode
You (and probably most other people) do not like this display though
why is List annotated with NotNull twice?
rustdocs*
it's not
it is
List is annotated, and the method is annotated
Oh my bad, I meant the parameters
I meant the parameter list
didn't see that
yeah I explained it badly, sorry
I haven't seen an explanation posted here for that ¯_(ツ)_/¯
it's exactly the same thing
the parameter and the type are both notnull
of course the type is not null
have you ever seen a method that accepts a nullable "type"?
how would it look like?
thats not what i mean
public void doSth(void ???)
it's a bit annoying because I went through the hassle of getting my fix-javadoc-plugin approved for the gradle plugin portal
Gradle portal is like the easiest place to upload things to, they accept almost everything if they are setup well and domain is confirmed
Super simple process and fast too lol
Far from a "hassle"
as in, the annotation is annotating both the type and the parameter
void has nothing to do with nullable
everything is a hassle if you gotta do it in your free time instead of working and get paid, that's what I meant with "hassle"
wdym?
then I don't understand what could be nullable besides the actual value that's being passed
yeah I also don't get it
ofc a String (class) is NotNull
I literalls just wrote it's a String
No one asked you to do the plugin nor no one asked you to PR, so if it is a hassle it was your choice to do it on your free time
I know that
the annotations indicate which values are allowed
I don't know where this discussion is going to lead to? Are we saying that everyone's contributions are pointless because they'll either get accepted or not anyway?
exactly. And hence the NotNull refers to the passed String, and not the fact that the next parameter is a string, itself
and hence it's imho wrong to have it in the javadocs twice
consider @Nullable List<@NotNull String> blah. The parameter is nullable, but the string type is notnull
yes
thats what it means to have a notnull type
yes, but this comes down to the fact that the annotation was created before TYPE_USE was added, so the PARAMETER target was kept for compatibility reasons - basically an issue with the annotation framework
obviously when you're annotating the top level type, it's the same as annotating the parameter
now run javadoc over your code and you'll end up with @Nullable @Nullable List<@NotNull @NotNull String> blah
yes, which is technically correct
it is not technically correct
the list type is nullable and the parameter is nullable
|| (@Nullable @Nullable List<@NotNull String> blah, at least in the screenshot above) ||
it perfectly fits what the annotation is configured to be
the paremter is not nullable
whats the diff between the two?
because you annotated it with NotNull
I did
when it's on the "top level" there is no difference, but i gave an example of when annotating a type is a real thing
I know when annotating a type is a real thing lol
then you will see that the parameter is annotated is nullable
ye I get the annotating the type inside, but ex if I do String, what's the diff between saying that the string type is nullable and the param is nullable?
Or is that only with types with generics?
this suggests you dont
what's the purpose of having both green NotNulls? What's the difference to having only one?
effectively nothing
is that a rhetorical question?
no
then again it's because both are nullable
