#help-development
1 messages ¡ Page 1399 of 1
for playing audio
i can send a video
so you can understand whats going on
if you want
i feel like it may have something to do perhaps with the sound needing to be stopped
before being replayed
Do anyone know after the installation of dreans always flying plugin in spigot what should we do
how can i use config.addDefault to add lists? like this
lore:
- 'testlore3'
- 'testlore4'
Pls tell me
#help-server
This channel is for development related problems
Ok sir
You can just call FileConfiguration#set(String, List<String>) to add a list to a configuration
yea i already figured it out
thanks
i foudn this online
String[] defaultLore = {"first Default Lore", "second Default Lore"};
config.addDefault("tiers.2.items.1.lore", Arrays.asList(defaultLore));
Looks alright đ
Could probably skip the array, but thatâll work
I like the verbosity đ
Fair
md5 if you're reading, feel free to @ me about my PR (the one about dimension advancements)
I'm getting tired of talking on stash lol
The docs say that "<command>" in plugin.yml is a macro for the command's name, right?
It's not doing it, I'm not sure if I'm doing it wrong
Or am I just being dumb and they're just saying "when we say <command>, we just mean the command name"
<command> is just the label iirc
In the docs, in the description for "usage" in plugin.yml, it says "<command> is a macro that is replaced with the command issued wherever it occurs."
Perhaps I'm not understanding, but doesn't that mean that for a command "foo", "usage: /<command>" will be replaced with "usage: /foo"?
Yes so the label of the command.
commands:
foo: <- This
description: Foo command
Should be
Right, but it doesn't seem to be working
"<command>" remains
I'm getting the usage via getUsage() by the way, not by returning false
That may be changing things
I think getUsage() just returns the raw String gotten from the yml section
Damn it
I didnât even know that was a thing
is there a compatibility layer for the bungee api?
so i can use ChatColor#of(String) on older versions (say, 1.12.2)
yes i know old version not supported
Rgb isnât in 1.12
yes i know
I see a lot if NPE possibilities in this code. And yout IDE does so too.
i'd like to be able to fall back to supported colors on <1.16
Probably need something custom
i see
Write against an interface and implement that version yourself.
hmm i don't see any npe error log
how do you mean "write against an interface"?
Right click with a stick for example
okay
its an example for what?
it would cause an npe?
Think so
why?
Has no lore
Also air has no meta
Ah wait you filter to only stone axes
Still a normal stone axe has no lore
Btw if you set the boolean to false in one line then it will stay that way in the 4 lines afterwards. So setting it to false and then checking if its false is kind of useless.
Ah right. Click with a normal stone axe
umm
an NPE won't cause the log to disappear for what ik
hmm lets see what ahppens if i use a normal stpone axe
how can i get the minecraft version as not string?
right NPE
return;
}```
What do you want it as other than string
fixed
oh for real??????
what why does java work that way
idk im trying to check for 1.16 or newer
so i just need to put a few lines between the setting and checking
What do you mean why does it work that way
hmm very reasonable
No. I mean that it will always stay false unless you change it. No matter how many lines you add in between
i did change it?
You set the Boolean to true, and then check if itâs false a few lines later
It will never be false at that point
ohhh shoot
You set it to false. So it will always be false in the both conditions after that
i set the wrong variable
wait..
Yeah false, thatâs what I meant
Arrays.stream(ChatColor.class.getDeclaredMethods()).anyMatch(x->x.getName().equals("of"))
lol
True and truenât
And please... press ctrl+alt+L when you are in your code
Or just catch a MethodNotFoundException when trying to get it via reflections
I mean relying on exceptions should be avoided
so the loc variable should have a world
If you initialize an instance with new then it will never be null
okie
but im setting variables here
cmd is an instance of the Commands class
when i did cmd.pos2 = e.getClickedBlock().getLocation();
it should give the pos2 variable the location value of the block
and that includes the world that the block is in
how to convert 24bit color to 16 colors
truncate the bit sections with a bit mask and some shifting
how?
I donât think they mean 16 bit color
im trying to convert RGB colors to ChatColor lol
I think they mean 16 colours
I think ChatColor has a method to get the color from awt Color? Maybe?
So ChatColor.of(awt.Color) then create a new awt.Color instance with your 24bits
yeah thats fine for 1.16
I think this existed for a while
im trying to return legacy colors for <1.16 servers
RGB chat colors have existed since 1.16 lol
wait hold on...
Yeah but i thought the was a method earlier that just translated the color
How is stockPlaceholder might be null? My IDE says that. https://paste.md-5.net/wavudevahi.js
I guess outOfStock might be null xD
?
yes, outOfStock and unlimitedStock might be null because I get the value from config.
but I gave a default value to the stockPlaceholder tho.
Yeah but you are setting it after that anyway
Doesn't matter if you have the "Placeholder Error!"
you'd usually apply the default after all possible "non default" values
so like a last if(stockPlaceholder == null) stockPlaceholder = "Placeholder Error!";
đ
mmm
one working color
consume all the cpu, yes
tfw my code is so slow it actually crashes the server
ai
nah
bitshifting
somehow this is like, super slow
no shit its slow
the for loop isnt for looping
oh fuck, right, bytes are signed
b < 255
0 - 64 - 128 - 192 - 256 (overflow)
Yeap soz didn't see that
You should probably use a NavigableMap<Integer, ChatColor> for that
Where the key is the rgb representation of the color
So you can just use a binary search to obtain the closest ChatColor from any given rgb int
so i'd have to generate a map of all the colors
Yes. You can do that once using 1.16 and then just hard coding the values
??
minecraft's data dumps have that data?
if i get it working i might make it available as a library
Thanks bungee...
null for non-rgb colors
Then getting the Keys for the NavigableMap might be a bit more tricky
nvm#
private static final NavigableMap<Integer, ChatColor> COLOR_MAP = new TreeMap<>() {{
this.put(11141120, ChatColor.DARK_RED);
this.put(16733525, ChatColor.RED);
this.put(16755200, ChatColor.GOLD);
this.put(16777045, ChatColor.YELLOW);
this.put(43520, ChatColor.DARK_GREEN);
this.put(5635925, ChatColor.GREEN);
this.put(5636095, ChatColor.AQUA);
this.put(43690, ChatColor.DARK_AQUA);
this.put(170, ChatColor.DARK_BLUE);
this.put(5592575, ChatColor.BLUE);
this.put(16733695, ChatColor.LIGHT_PURPLE);
this.put(11141290, ChatColor.DARK_PURPLE);
this.put(16777215, ChatColor.WHITE);
this.put(11184810, ChatColor.GRAY);
this.put(5592405, ChatColor.DARK_GRAY);
this.put(0, ChatColor.BLACK);
}};
public static ChatColor chatColorFromRgb(final int rgb) {
final int lower = SpigotCore.COLOR_MAP.floorKey(rgb);
final int higher = SpigotCore.COLOR_MAP.ceilingKey(rgb);
final int result = (rgb - lower) <= (higher - rgb) ? lower : higher;
return COLOR_MAP.get(result);
}
public static ChatColor chatColorFromAwtColor(final Color color) {
return chatColorFromRgb(color.getRGB());
}
This is what i came up with. Works.
This should honestly be a feature in the api...
That says null for formatting lol
Bold, underline etc
Ah? Neato
I mean it returns null if the ChatColor instance is not created using the rgb syntax
So it returns null if you pass it ChatColor.RED?
Wait... now it doesnt.
We could make it a library, for the people who want it
Coz i doubt md5 would accept it as a feature request
Oh i see my mistake. I iterated over all ChatColor constants and it threw a NPE when it hit formatting ones
Whatever. I have my map now anyways
So far ive bothered writing a console compat function. For rgb colors
(replaces all color codes with ansi sequences)
How do you mean?
I have a function rhat takes in a mc formatted string and returns an ansi formatted one
So my rgb test works in console
ah right
@lost matrix that code is very meh
You want closest distance in the 3d projection
Square and sum the components
Eh. Right. Didnt think about that
So easy fix actually
Not sure what you mean by that. I was just thinking about using the angle between the rgb vectors as comparator for the NavigableMap
I would wait. Because md_5 just brought up a good point. The color you get is not the closest one to your input in terms of the color space but the raw bits
its pterodactyl
fair enough
Im currently thinking about a performant way for the comparator implementation
im getting flooded :<
@lost matrix your code failed at final int lower = COLOR_MAP.floorKey(rgb);
Uh. Sure. Then use a method that includes the current or something idk. Im currently on the rgb vectoring thing
?paste
I kind of eyeballed this one so if you have feedback go ahead:
https://paste.md-5.net/ayahuyaham.java
Wait i can also just pollute the chat with this one
private static final int[] ZERO_COLOR = new int[]{0, 0, 0};
private static final Comparator<Integer> RGB_ANGLE_COMPARATOR = (colorA, colorB) -> {
int[] vecA = SpigotCore.splitToRgbVector(colorA);
int[] vecB = SpigotCore.splitToRgbVector(colorB);
return (int) (SpigotCore.angle(vecA, SpigotCore.ZERO_COLOR) - SpigotCore.angle(vecB, SpigotCore.ZERO_COLOR));
};
private static final NavigableMap<Integer, ChatColor> COLOR_MAP = new TreeMap<>(SpigotCore.RGB_ANGLE_COMPARATOR) {{
this.put(11141120, ChatColor.DARK_RED);
this.put(16733525, ChatColor.RED);
this.put(16755200, ChatColor.GOLD);
this.put(16777045, ChatColor.YELLOW);
this.put(43520, ChatColor.DARK_GREEN);
this.put(5635925, ChatColor.GREEN);
this.put(5636095, ChatColor.AQUA);
this.put(43690, ChatColor.DARK_AQUA);
this.put(170, ChatColor.DARK_BLUE);
this.put(5592575, ChatColor.BLUE);
this.put(16733695, ChatColor.LIGHT_PURPLE);
this.put(11141290, ChatColor.DARK_PURPLE);
this.put(16777215, ChatColor.WHITE);
this.put(11184810, ChatColor.GRAY);
this.put(5592405, ChatColor.DARK_GRAY);
this.put(0, ChatColor.BLACK);
}};
private static int[] splitToRgbVector(final int color) {
return new int[]{(color >> 16) & 0xff, (color >> 8) & 0xff, (color) & 0xff};
}
private static double angle(final int[] vecA, final int[] vecB) {
final int xa = vecA[0];
final int ya = vecA[1];
final int za = vecA[2];
final int xb = vecB[0];
final int yb = vecB[1];
final int zb = vecB[2];
final double med = xa * xb + ya * yb + za * zb;
final double lenA = Math.sqrt(xa * xa + ya * ya + za * za);
final double lenB = Math.sqrt(xb * xb + yb * yb + zb * zb);
return Math.acos(med / (lenA * lenB));
}
Ah... this still doesnt quite hit the mark actually...
Because multiple colors can have the same angle to zero
Easiest way to test would be to print a bunch of letters in a 3 layer for loop
Ill do that
Id recommend making a for loop for each channel
0-255 or whatever max is in java
Anyways, intervals
Lemme grab my pc
I just use this
for (int r = 0; r <= 250; r += 50) {
for (int g = 0; g <= 250; g += 50) {
for (int b = 0; b <= 250; b += 50) {
final Color color = new Color(r, g, b);
final ChatColor trueColor = ChatColor.of(color);
final ChatColor fetchedColor = SpigotCore.chatColorFromAwtColor(color);
System.out.println(trueColor + "XXX §r>> " + fetchedColor.toString() + "XXX");
}
}
}
But it pretty much always resolves black
Eh...
Fun, my pc bluescreened
F
Ah good idea
Oh right because 32bit colors because blocks
Ah fuck bluescreened again
private static double getDistance(@NotNull Color c1, @NotNull Color c2) {
double rmean = (c1.getRed() + c2.getRed()) / 2.0;
double r = c1.getRed() - c2.getRed();
double g = c1.getGreen() - c2.getGreen();
int b = c1.getBlue() - c2.getBlue();
double weightR = 2 + rmean / 256.0;
double weightG = 4.0;
double weightB = 2 + (255 - rmean) / 256.0;
return weightR * r * r + weightG * g * g + weightB * b * b;
}
Thats what we need
Have you tried shutting it off, waiting for 5 seconds and starting it again?
Tried ro do a hard shutdown during boot tp get to safemode and now it doesnt power on anymore
Yes i have
It litterally doesnt power on anymore
And i cant reseat battery coz its non removable
Apple?
MSI
Anyways im not quite sure how to implement that in O(log n) complexity. Its only working with iterating over all keys so far...
Oh i see. Spigot also does it in O(n)
Time to download intellij on my phone
Hm?
Does that even exist
Yes
I think im close
If you thonk hard enough
Some are more accurate, others not so much
what's the difference between PacketPlayOutParticles and loc.getWorld().spawnParticle()
One is a packet sent to the player, one spawns a particle in the world
ah okay
The world one sends particles to all players in the world and the PacketPlayOutParticles packet can be sent to one single user.
But i think player also has methods for showing only him the particles.
which one performs better?
Oh god...
It does the same thing so its identical in terms of performance.
Basically
If you're using packets to spawn particles your an idiot
The API has literally always been a near direct mapping to the packets
There is literally no excuse for using packets
i mean, i just wanna show the particles to the player im sending the packets to
There's particle methods in Player
My laptop is dead
đŁ
Rip
And i need a pc for school
Whenâs school, today?
Today till friday
am i being really dumb or why does this not work
`@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(command.equals("check")) {
Player player = (Player) sender;
PlayerInventory playerinv = player.getInventory();
if (playerinv.contains(Material.BARRIER)) {
playerinv.remove(Material.BARRIER);
player.sendMessage(ChatColor.RED + "Illegal items were removed from your inventory!");
}
}
return true;
}`
```java
your code here
```
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(command.equals("check")) {
Player player = (Player) sender;
PlayerInventory playerinv = player.getInventory();
if (playerinv.contains(Material.BARRIER)) {
playerinv.remove(Material.BARRIER);
player.sendMessage(ChatColor.RED + "Illegal items were removed from your inventory!");
}
}
return true;
}
It's worth it for the better formatting
That should work, perhaps there are no Barriers in the inventory?
PlayerFishEvent.State.REEL_IN```
It says the event "REEL_IN" doesn't exist, im using spigot 1.12.2, does anyone know a fix?
there are
does bungeecord allow for global banning at once on e.g. 8 servers?
do i need to install a plugin in bungeecord. to ban on all servers at once?
Hello, Anyone has Protocollib dependency and repository?
is there an event for when a player begins to draw their bow back?
kind of like BlockDamageEvent
Thanks <333
actually i guess PlayerInteractEvent could work
bump
what does it show under PlayerFishEvent.State
@sage swift
How can I make slime that I can click through, can't beat, etc. I've tried slime.setInvulnerable(true); but it doesn't work
this is in 1.13.2 so i think REEL_IN wasnt added in 1.12.2 yet :/
how do I cancel a runnable?
Bukkit.cancelTask(id) but depending how you create/start the task there are other ways.
That's how I start it: Bukkit.getScheduler().runTaskTimer(plugin, () -> {
Are you trying to stop the task inside the runnable? if so cancel()
only cancel()?
Bukkit.getScheduler().runTaskTimer(plugin, () -> {
cancel();
}
}, 20, 20);
correct?
looks right
cancel() doesn't work. It's red underlined
Oh cause its not in a runnable.
Dojava int i = 0; i = Bukkit.getScheduler().runTaskTimer(plugin, () -> { Then instead of cancel do Bukkit.cancelTask(i); I think that should world
command isn't a String.
@brittle nova did that work?
when I do "Bukkit.getScheduler().cancelTask(i);" it says that i isn't correct
Variable used in lambda expression should be final or effectively final
Im trying to make a dupe plugin that requires a client or a mod
Uggg complicated lol...
new BukkitRunnable() {
public void run() {
// cancel();
}
}.runTaskTimer(Plugin, delay, time);
But i dont know how
mm
Like the book dupe
java streams yes
When I do "Bukkit.getScheduler().runTaskTimer(plugin, new BukkitRunnable() {" it says that runTaskTimer is deprecated
What should I do?
but when it is a bukkitrunnable not a runnable there is a method called cancel()
Use the method I show above.
Its the same thing but alittle cleaner
Hi!
I have a small question. What do I need to remember to write efficient plugins? I'm new to it and unfortunately I make some mistakes with it...
Tidy code
That you can't be worse then anyone else.
kinda looks like a carrot tbh
@lost matrix any luck? lol
PlayerFishEvent.State.REEL_IN``` Does not exist within spigot 1.12.2, does anyone know how i can still check for this event to happen?
probably check for failed attempt/caught fish/other possibilities
Those dont act the same as reel in :/
out of date = bad
i cri
Player#setCooldown(Material.BOW) works... almost. every once in a while the player charges the bow despite the cooldown bar appearing. is there a better way to handle stopping the use and in this case charging of an item than the cooldown?
oh hell no
Running natively on my phone
got it to work with the or logical operator
(event.getState().equals(PlayerFishEvent.State.IN_GROUND) || event.getState().equals(PlayerFishEvent.State.FAILED_ATTEMPT))
O f f l i n d
i admire your dedication to the craft
How can I make slime that I can click through, can't beat, etc. I've tried slime.setInvulnerable(true); but it doesn't work
doesn't work
What exactly are you trying to achieve?
not entirely sure that even is possible without not sending the slime to the client
Depends what he's trying to do. Raytracing is always an option
Yeah
listen to EntityInteractEvent or whatever
and raytrace
and fire the proper events lol
I want to make slime, which's hitbox is on my head and i can't beat etc.
You are trying to set a slime to look like your head but you are finding when you left or right click you are hitting the slime?
yeah
and setCollidable didn;t work
afaik setCollidable only changes its collision?
In that case try adding the Slime UUID to the players https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/LivingEntity.html#getCollidableExemptions()
Yep, I was hoping it would prevent interactions too
A shame Teams can't accept LivingEntities
which plugin is that?
How clone Packet?
SpigotAV
thanks
@vagrant stratus it'd be real ironic if the malware finder had malware in a compiled version /hj
only scans one thing, which my Anti-Malware already deals with đ
lmao
Ye
How I can clone Packet?
bruh they do be promoting yatopia
Checks for javaassist, .l1, and .l_ignore but that's about it
ooof
Yea, also... for funisies.. gimme a sec
time's up
assuming there's a compiled jar...
i really don't wanna compile it just to prove a point..
well yeah i started like, this weekend
@vagrant stratus check releases lol
who pinged
ok
IDE froze (âŻÂ°âĄÂ°ďźâŻď¸ľ âťââť
lmao fun
oh it's fixed uwu
meanwhile intellij on phone
intellij on phone
oh this is always fun đ¤Ł
what is?
You'll see
oh no
How I can clone Packet?
packet.clone don't work
There's one very important reason why anti-malware plugins will NOT work
sechz?
well yes because jars are mounted before that, so you cant PREVENT it
i never claimed to prevent it
pretty much, and you using S gives basically the entire alphabet to mess with your shit
?
anti malware plugins are dumb
^
only way to be sure is to decompile or look at source
i mean, at least itll run on hosts
and if it's obfuscated, just not use it
EWG be like
if its obfuscated
yeah well fuck ewg
oh so, 99% of paid plugins?
yes
At least mine can't be easily disabled âşď¸
99% of paid plugins are trash anyway
how so?
if your code is shitty enough to want to hide then i don't wanna be running it
you got code to enable the plugin on disable?
because they are obfuscated and closed source so they don't get the benefit of open source contributors
you'll see
strangely enough songoda's premium plugins are open source
doesn't make them any less shit though
Assuming best case scenario
ok but nothing malicious right? @vagrant stratus
just asking before i execute it lol
How I can clone Packet?
packet.clone don't work
Nope, it's a plugin though. Wold have to have your av in the plugins folder too :p
well yeah its a plugin
ploogan
again, best case scenario :p
true
what am i looking at
i could make my plugin rename itself
doesn't matter as long as something loads before it
like what is it trying to do
all my plugin did is load before theirs, and then delete the jar :p
shows how vulnerable plugin based AV's are
and why i went with the approach i did :p
yeah i have no idea what you're talking about
AV in this case is Anti-Virus.
My Anti-Malware is a third party program, which means it's not loaded as a plugin
SpaceDash's however is, so to deal with it all a malicious plugin needs to do is load before theirs
and then delete their file
quite literally rendering the plugin useless
so which ones are being run in the screenshot
Mine
https://github.com/MeGysssTaa/keiko-plugin-inspector/ suffers the same issue
How I can clone Packet?
packet.clone don't work
ProtocolLib probably has a way
without protocolib (I must edit spigot)
just instantiate a new packet with the required parameters i suppose
is it possible to get what's in a player's chat text field?
Hello, how to make a easy Scoreboard?
every time the player writes a new character in the text box, they send a tab complete request to the server
by keeping track of these requests you can monitor what players write in real time
although i think that's only limited for commands actually
so yeah you're kind of fucked unless it's a command
Another way you can deal with it @solemn shoal is this
but I want clone packet no create new with parametrs in constructor I want clone
why
@vagrant stratus hm?
what
If you know how to check code, you'll know :p
If you don't, then learn because you'll need that knowledge if you'll take the project seriously....learn about deobfuscation too
hmm
how long have you been working on this anti malware thing
because I vaguely remember running into some guy on some libtard discord who was working on something very similar
and I think that might have been you
https://www.spigotmc.org/resources/spigot-anti-malware-detects-over-300-malicious-plugins.64982/
First Release:
Feb 25, 2019
I remember getting banned because I said I would not purchase a product from a chinese person if they didn't know english
which was apparently racist and ableist
2019 huh
i'm not sure then
might pull some logs later and check
as of the first release
383 malicious plugins have been found
73 different malicious devs get automatically banned
257 different checks have been implemented
have I seen you on this guild before
this one specifically?
Maybe
because your name is familiar and if it isn't from here it's probably from that libtard guild
it's a strange premonition and it's disconcerting
but whatever i guess
what's the name of it?
i have no clue
it was like some minecraft server or plugin community or something I think
ah, paper's discord maybe?
I've been on there once or twice
nah
but i might remember you from there then
got banned from there too because apparently supporting 1.8 builds is a crime
It might even violate the Geneva Conventions as far as im concerned
geneva convention more like geneva suggestion
3 days lol
ItemStack[] contents = sellitem_seller.getInventory().getContents();
int counter = 0;
for (int i = contents.length; --i > -1;) {
if (contents[i] != null && contents[i].isSimilar(sellitem_sell_item)) {
counter += contents[i].getAmount();
}
} ItemStack[] contents = sellitem_seller.getInventory().getContents();
int counter = 0;
for (int i = contents.length; --i > -1;) {
if (contents[i] != null && contents[i].isSimilar(sellitem_sell_item)) {
counter += contents[i].getAmount();
}
}
How can I modify this to give me the amount of items matching a specific ItemStack, WITHOUT the ItemName?
Because DisplayName of sellitem_sell_item is null
wut
so at the moment that there gives me the amount of items matching an ItemStack
You've got a lot of work to do, have fun trying to deal with the one major thing that render your project useless too :p
do you want the isSimilar to ignore the display name?
But I want it to give me the amount of items matching the ItemStack but with any DisplayName
yeah uh you might have to reimplement isSimilar
so DisplayName can be anything, idc what
thanks
contents[i].isSimilar(new ItemStack(sellitem_sell_item.getType()))
welcome đ¤Ł
But seriously though, that really should be your main concern as an AV dev
but also all item meta
that deesnt match any other data
you might as well compare just materials by that point
fair enough
cant
Because then I would loose support for custom items
Which I definitely need as its a shop plugin
time to make my plugin move itself on disable @wraith rapids
yeah you'll have to reimplement a version of issimilar that ignores display name
Then you can't limit your check to just isSimilar
thats why I am here
my anti malware related suggestion would be to give up
what why
You have to manually check the other data then
can I not somehow for each contents in there set the DisplayName to null?
all anti malware does is give people a inflated sense of security and makes them do dumb shit that gets their system infected down the road
You could but then you still wouldn't get accurate results with isSimilar()
well if the displayname of contents and the one of sellitem_sell_item is null itll work
Ehhh, mine at least detects a lot of stuff & can't be easily deleted :p
Found malicious plugins that were uploaded in 2016
loadBefore: spigotav
lol
that would work too
How I can clone PacketPlayOutMapChunk
new PacketPlayOutMapChunk
but clone
not if i randomise my spigot.yml
+- and I want deep clone xD
randomize it then, we'll see how difficult it is
lol ok
plugin.yml >> name: !<name>
?
So I reimplement that and set the DisplayName for the metadata to null?
plugins are usually loaded in ABC
then deep clone the data
they are loaded in whatever order teh platform responds to listfiles
and iirc the plugin description file is loaded way before any plugin code is even executed
so you might have a difficult time changing it at runtime
i remember someone trying to set their api-version based on the server version and running into that issue
lol
api version is fucking dumb
if I set it to a too low of a value, I get stupid material issues like crossbows showing up as air
if I set it to too high of a value, the plugin doesn't load on older versions
Keeping backwards compatibility is great, isn't it
what happened to me, the developer, being able to write version compatibility?
I generally have no issues.
i am perfectly capable of writing a plugin that is backwards and forwards compatible
api-version just makes it so much more annoying
I believe I've found a solution to dealing with a randomized plugin.yml files, I just need to wait on @solemn shoal to do something đ
it tries to do it for you, and it fucking sucks at it
ah?
Ye
some of the more notable issues are ItemStacks in inventories appearing as air, because their material exceeds your api-version
same happens for blocks
public static void setField(final Object packet, final String field, final Object value) throws NoSuchFieldException, IllegalAccessException {
final Field f = packet.getClass().getDeclaredField(field);
f.setAccessible(true);
f.set(packet, value);
}```
Use this?
plenty of rtp plugins without an api-version specified have the issue of teleporting people inside physical blocks, because they see those blocks as air
I haven't had that issue...
Can I have some help with reimplementing the isSimilar without DisplayName checks?
well, it still happens
try it; call Block::getType() on a nether gold ore or whatever they're called
with api-version unset
it's gonna be air
ItemStack::getType() on a crossbow or a trident will also return air
so fuck you if you're trying to find empty slots in a player's inventory or something
Hvae you looked at teh isSimilar method?
kinda
@wraith rapids to deep clone use setField?
I just dont know how reimplementations work
well, the simplest reimplementation is
- copy the code
- modify the code
- call your modified code instead of the original
yeah I tried that
however that said, the itemstack isSimilar impl is pretty absurd
it redirects all over the place
but I dont know how to properly get the copied stuff working
exactly
and is implemented in bits and pieces across a million itemmeta classes
Isnât it basically same as equals just ignoring amount
or maybe better implements cloneable? to PacketPlayOutMap? @wraith rapids what you think
Yeah big oof time
set api version to none
okay then maybe another way
Can I for every item in counter set its displayname to null?
ItemStack[] contents = sellitem_seller.getInventory().getContents();
int counter = 0;
for (int i = contents.length; --i > -1;) {
if (contents[i] != null && contents[i].isSimilar(sellitem_sell_item)) {
counter += contents[i].getAmount();
}
}
its not called a lot
i don't think you really have an alternative though
only when people sell items
?jd
package index
yeah just wait until people try to sell an inventory full of shulker boxes lol
okay then how would I do that
Im not making them able to sell shulkers -.-
set sellitem's display name to null
and then set the display name of every item in contents to null
yeah breaks everything. But my point was you can set it to 1.13 and it would work fine for any higher versions. And only 1.13+ checks for it anyways.
i super vaguely remember having issues even with it set to 1.13
but i could be wrong i suppose
like, having api version set to 1.13 and having some but not all materials showing up as air
mhm
what happens if I just spawn a thread in my ctor and preload all of my classes to memory so you deleting the jar doesn't really affect anything
or does your av thing kick in before the plugin ctor is called
yeah i don't know i could have been drunk then
ItemStack[] contents = sellitem_seller.getInventory().getContents();
int counter = 0;
for (int i = contents.length; --i > -1;) {
ItemMeta invmeta[i] = contents[i].getItemMeta();
contents[i].setItemMeta(invmeta[i]);
if (contents[i] != null && contents[i].isSimilar(sellitem_sell_item)) {
counter += contents[i].getAmount();
}
}
How do I get this working
i guess things aren't ass horribly bad as I thought
that's good
well, uh
why is invmeta an array
or rather
why are you declaring a single ItemMeta variable
and then accessing it as if it were an array
because I am trying to get each items itemMeta
myes, but you see
you are getting each item's meta, one at a time
you are processing a basket full of apples
but you are only doing stuff with one apple at a time
thats why I have [i] I thought
you only need one apple sized hole to put the apple you're processing in
change ItemMeta invmeta[i] = contents[i].getItemMeta();
to
ItemMeta invMeta = contents[i].getItemMeta();
and then?
if it were an array, you'd do ItemMeta[] invMeta = new ItemMeta[10]
which would create an ItemMeta array of size 10, and put it in a variable called invMeta
okay
you'd then call invMeta[n] to get the n'th element of the array
but none of that is necessary here, as you only need to hold onto one item meta at a time
because we're only processing one item stack at a time
yeah true
anyway, isSimilar does basically 2 things
first, it compares the Material of the item
second, it checks if the getItemMeta of the items are equal
yeah I looked at it in its own implementation
equals would in addition to this check if the getAmount's are equal
now, getting an itemstack's itemmeta is expensive
because bukkit is trash
setting an itemstack's itemmeta is also expensive
so, let's just not do that
it also doesnt work
instead of setting the itemmeta of the inventory item, just test the two separately
because if a slot is empty it gives an error
null check
if (Objects.equals(a.getType(), b.getType()) && Objects.equals(a.getItemMeta(), b.getItemMeta()))
yes
a block logging plugin
the above snippet is what isSimilar does, in essence
yea
it has some tweaks and shit but they're mostly redundant
now, we already have the item meta of item B
because we had to modify that item meta
to set the display name
implement the methods of CoreProtect yourself
and log every single block interaction
so, instead of putting that modified itemmeta back into the stack and then comparing the stack, we want to compare the meta
if (Objects.equals(a.getType(), b.getType()) && Objects.equals(metaA, metaB))
metaB is the ItemMeta you get from the stack in the inventory
before calling this, you would set the display name to null
and before the entire loop, you get the comparison item's ItemMeta
and also set its display name to null
and you get something like this
ItemStack[] contents = sellItemSeller.getInventory().getContents();
int counter = 0;
ItemMeta metaA = itemA.getItemMeta();
metaA.setDisplayName(null);
for (int i = contents.length; --i > -1;) {
ItemStack itemB = contents[i];
if (itemB == null || itemB.getType() == Material.AIR) continue;
ItemMeta metaB = metaB.getItemMeta();
metaB.setDisplayName(null);
if (Objects.equals(itemA.getType(), itemB.getType()) && Objects.equals(metaA, metaB)) {
counter += contents[i].getAmount();
}
}
for (int i = contents.length; --i > -1;) {
if(contents[i].getItemMeta() != null) {
ItemMeta invMeta = contents[i].getItemMeta();
invMeta.setDisplayName(null);
}
if (contents[i] != null && Objects.equals(contents[i].getType(), sellitem_material) && Objects.equals(itemmeta, invMeta)) {
counter += contents[i].getAmount();
}
}
I'd have done it like this
that will blow up if any of the itemstacks in contents[] is null
and also you are declaring invMeta in the scope of the first if block
the second if block won't remember it
Modified isSimilar to compare stacks ignoring amount and custom name ```java
public boolean isSimilar(ItemStack source, ItemStack compare) {
if (source == null || compare == null) {
return false;
}
if (compare == source) {
return true;
}
ItemStack sourceStack = source.clone();
ItemStack compareStack = compare.clone();
if (sourceStack.hasItemMeta() && sourceStack.getItemMeta().hasDisplayName()) {
ItemMeta meta = sourceStack.getItemMeta();
meta.setDisplayName(null);
sourceStack.setItemMeta(meta);
}
if (compareStack.hasItemMeta() && compareStack.getItemMeta().hasDisplayName()) {
ItemMeta meta = compareStack.getItemMeta();
meta.setDisplayName(null);
compareStack.setItemMeta(meta);
}
Material comparisonType = (sourceStack.getType().isLegacy()) ? Bukkit.getUnsafe().fromLegacy(sourceStack.getData(), true) : sourceStack.getType(); // This may be called from legacy item stacks, try to get the right material
return comparisonType == compareStack.getType() && sourceStack.getDurability() == compareStack.getDurability() && sourceStack.hasItemMeta() == compareStack.hasItemMeta() && (sourceStack.hasItemMeta() ? Bukkit.getItemFactory().equals(sourceStack.getItemMeta(), compareStack.getItemMeta()) : true);
}```
probably. Not tested
instead of metaB you mean itemB right?
ok lemme test it
next thing you should look into is probably something called 'scope'
basically, if something is declared inside a pair of { }
it will be forgotten when the } is reached
that I know
needs to be declared before
but can be modified anywhere
in this for example
for (int i = contents.length; --i > -1;) {
if(contents[i].getItemMeta() != null) {
ItemMeta invMeta = contents[i].getItemMeta();
invMeta.setDisplayName(null);
}
if (contents[i] != null && Objects.equals(contents[i].getType(), sellitem_material) && Objects.equals(itemmeta, invMeta)) {
counter += contents[i].getAmount();
}
}
you declare invMeta inside a { }
yea
ah ok
for (int i = contents.length; --i > -1;) {
ItemMeta invMeta;
if(contents[i].getItemMeta() != null) {
invMeta = contents[i].getItemMeta();
invMeta.setDisplayName(null);
}
if (contents[i] != null && Objects.equals(contents[i].getType(), sellitem_material) && Objects.equals(itemmeta, invMeta)) {
counter += contents[i].getAmount();
}
}
it would have to be like this
also what on earth are you trying to do vinny
vinny?
vinny7
posted some weird ass code snippet and asked a question that they now deleted
oh lol
String[] sword = { "SWORD", "PICKAXE", "AXE", "SHOVEL", "HOE", "BOW", "ROD", "STICK", "BONE"};
if (materialName.contains(sword.toString())) {
Bukkit.broadcastMessage("funfou");
}``` this
null ?
i found it
public static boolean contains(String input, String[] items) {
return (Arrays.asList(items).contains(input));
}```
That will fail if its a GOLDEN_SWORD
I would need this actually for a command's arguments, where I can check three numeric arguments to be able to show the player
what are you trying to do
when a player executes the / loot command create string will call a method that will appear an armor stand below it where you performed it, like this:
in this case, i would do more for future projects the possibility of the player being able to rotate the head of the armor stand with the item to make the item be on the wall, anyway
so every time the player changes the argument in the chat as / loot rotate x y z, the x, y, z would be numbers and would show the player what the position would look like without the player executing the command to see understand?
i hope the translator doesn't get in the way
use a precomputed Set
array/list contains is slower
and set represents what you want to do more accurately
and don't create a new array/set/whatever every time, precompute it
precomputed Set ?
yes
what is this
create a set once at startup, put the Strings in it
and then use that same set every time
what you are doing now is creating a new array every time
What's the best way to save statistics etc when dealing with bungee servers
then you mean like a camp ?
wut
give me an example
private static final Set<String> myStrings = new HashSet<>();
static {
myStrings.add("peepeepoopoo");
}
does not need to be static nor final, the point is that you don't create a new set or list or array every single time
you reuse data which has already been created
so you don't need to compute it every time
it's a pre-computed resource
but the question of whether this item is in that hash?
so in order to initialize the plugin would i add these strings?
yes
oh, i never got to use that, but thanks
in my case, I filled the Set in a static {} block, which is executed when the class is initialized
that is, once and exactly once, and before any of the code in the class is run
I always think of your username as NNN instead of NNY
and I always read it as no nut november
lmao
mmm
eternal and never-ending NNN
can I not uncancel a BedEnter event
that is cancelled cuz of the reason NOT SAFE
I got the detection but event.setCancelled(false); doesnt seem to work
set priority to monitor and check, might not be possible tho
uh how will I do that in an event tho
in @brave glenHandler add (priority = EventPriority.MONITOR)
yea
rip @brave glen for all the pings he gets
ikr
@brave glen
yea
rip @brave glen
only superior clients like ripcord are immune
still doesnt owrk :P
Is there an event for an inventory changing (add/remove an item)?
Could that do?
more or less
this is what I have got idk what I did wrong ```
@EventHandler(priority = EventPriority.MONITOR)
public void sleep(PlayerBedEnterEvent event) {
if(event.isCancelled()) {
if(event.getBedEnterResult().equals(PlayerBedEnterEvent.BedEnterResult.NOT_SAFE)) {
event.setCancelled(false);
event.getPlayer().sendMessage("Yes");
}
}
}```
yeah ig I can remove the isCancelled check
you might have to do some funky packet sending instead of uncancelling it
I dont think bukkit reads event mutations after HIGHEST
unsure but yeah the name monitor is somewhat self explanatory
i don't remember such a distinction being made in most events
it's more just best practice and "don't do that"
You should NEVER attempt to modify an event in MONITOR
ah well that might be the case then NNY
huh why?
because MONITOR is for monitoring
the point to monitor's existence is that you can see what happened to the data
HIGHEST?
what plugins did to it
All plugins expect MONITOR to be the final result of the event. no changes at that point
if someone changes the data during monitor, there is no guarantee that any listener on MONITOR sees the right data
because someone might modify it later
that's why monitor is sacred and should be read-only
yep
@EventHandler(priority = EventPriority.HIGHEST)
public void sleep(PlayerBedEnterEvent event) {
if(event.getBedEnterResult().equals(PlayerBedEnterEvent.BedEnterResult.NOT_SAFE)) {
event.setUseBed(Event.Result.ALLOW);
event.getPlayer().sendMessage("Yes");
}
}``` works
it was setUseBed ig
I would argue for that you should use == for enum constant comparison
Not because equals doesnât work
But it will be negligibly faster
no point in not doing it
you probably want to get used to it
Uh well itâs sort of it a reference equality, as NNY said earlier if the unit a == b if and only if thatâs the case then a is b but then we can infer if a is b then a == b.
yeah I guess im just not used to the double =
== should be used for identity elements and primitives
it implies intent and understanding that this is indeed an identity element or a primitive
Thatâs totally fine, then you have something new to learn 2day (:
yep
you know what grinds my gears
tell me
a bunch of sand
that none of the navigable collections and maps are actually navigable
are they?
I mean. You can pass your own Comparator implementations
they're sorta navigable but it's shit
I wonder what SpaceDash has planned đ¤
yeah I guess they aren't "unnavigable" to say at least
i mean, the only way to get a next or a previous element is by going through the entire collection all over again
i was just doing a code and i found out that int cant be null but Integer can
you can't store a pointer inside the map and then navigate from there to the surrounding elements
you can just ram your massive bony fucking head into the map over and over again
da fuc
thats so weird lol
Uhm...
that's because int is a primitive and Integer is an object
I mean not really just how java is
when you have a Integer myInteger = new Integer(10), you are creating an Object of type Integer, storing a primitive value of 10 in it, and then storing a reference to that object in a variable named myInteger
that reference may point to nothing; such a reference would be a null pointer, or null
however, when you do int myInt = 10
you are directly allocating 32 bits worth of space on the stack
and storing the raw number 10 in those 32 bits
Integer is literally smtng like
class Integer {
int i;
}
like any other class I guess
that variable will always have a value; even if it's 0, which for a reference would be null, it's still a value
0 is 0
None of the primitives can be null, but the wrapper types can
if(enchantName != null){
Integer enchantLevel = getEnchantLevel(currentTier,items);
if(enchantLevel == null){
enchantLevel = 1;
}
finalItemMeta.addEnchant(Enchantment.getByName(enchantName), enchantLevel, true);
}```
why does this say that enchantName might be null when i already checked if its null or not
Show a screenshot of your code pls
and the warning
^
thats the warning
code
not enchantName might be null
yea
what if an enchant does not exist by that name?
then it will be null
even if enchantname is not
Thats why you should always go the verbose route if you are still learning. Allocate a new Enchantment variable and check for null on it.
i had to literally write my own implementations of treemaps and shit to make them properly navigable
i'm sure I could have found some properly navigable impls somewhere but I didn't have the effort to search
Can you guys give me some simple things to practise :p
do a backflip
already did that
Figure out how spiders work
- A plugin that tracks all the damage a player has received with a
/damagehistorycommand. - A simple tpa plugin
- Simple warps
- A plugin that uses the BossBar to display the health of the last attacked entity
thanks
i guess a rtp plugin is more for paper
since spigot plebians still don't have async chunks
Huh?
I dont get why that would hinder you from writing a rtp plugin
you can, but it's far more straight forward on spigot
Ah i see
since you don't need to deal with futures or threading or concurrency or anything of the like
which would have been the main focus of the practice
So calling the chunk async and reacting on the future with a tp to learn them
that would be the trivial implementation yeah