#help-development
1 messages Β· Page 114 of 1
there are only a few rare instances where I actually like to enforce exceptions
smh
player between 3-16 blocks away: follow
otherwise: stop
Trycatch from a clock cycle perspective is a bit slow
add debug statements
and see what they print
check what I sent above
yeah well if you say "its fine ", then no need to debug anything lol
I only throw exceptions when I'm doing something extremely wrong
I got a method for that, 1 sec
like trying to load a template that never existed
But from an API point of view, getting a canvas frame at the exact location of the pixel might return null sometimes
it'd be extremely unsettling if I got a result during my optimized calls because I make sure to validate my inputs
yet it's still a very valid possibility
line 149 is only for materials, line 172 is for actual itemstacks
Do you really hate regular for loops so much that you go atomic just to have a 1 line stream smh my head
wdym?
also items might be null
but what I sent uses regular for loops
not sure how the stream handles that
int amount = 0;
for(ItemStack item : inventory.getContents())
if(itemStack.isSimilar(item)) // not the other way around, nullability
amount += item.getAmount();
return amount;
add braces if you want
I've been adding braces lately but my hands are hella sweaty and it's uncomfortable to type
the good thing about open source is, that I can just say this:
"Pull request it if it bothers you" π
fuck no I'm not importing your lib into my IDE
if you dont fix it yourself, you must not complain π
PR every character change separately
consider it merely as a fine suggestion towards a replacement
I'll make 1 commit per character change
then have a PR with like 200 commits
yes, will do. I think you're also right about the stream thing breaking when a slot is empty
and hide some malware in one of them towards the middle
but on the other hand
it seemed to have worked by now
so I guess it's fine
EVERYTHING that's inside JeffLib is used somewhere in one of my plugins so I guess it does actually work fine
Time to PR and change that /s
Does anyone know how to store data about a player in spigot
what MC version?
1.19.2
ok
i see
how would i use to make a cooldown for running a certain command
would i like remember the time last sent
I also got a class for that
1 sec
ty
example usage:
public class MyCommand extends CommandExecutor {
private final Cooldown cooldown = new Cooldown();
public void onCommand(...) {
if(cooldown.hasCooldown(sender)) {
sender.sendMessage("You gotta wait before running this again!");
return;
}
cooldown.setCooldown(sender, 60, TimeUnit.SECOND);
// Do your stuff. Players can only run this every 60 seconds
}
from me? never
maybe you can take some inspiration from mine
I just use ACF β€οΈ
fuck
i dont get the hate against ACF
I just don't like annotations tbh
also seems jank to shade like 200kb worth of parser stuff
annotations use reflections
and I'm a performance freak
but who cares whether your plugins takes 20ns to enable, or 7ms?
I go to bed, spin for an hour, and get back to work because I want to optimize that 1 tiny method
code for another 3 hours and then sleep
idk I wouldnt bother about stuff like that
when people send a spark or timings report, then it's time to start optimizing stuff
but before that? naaaah thanks
this isn't what the image says
noone ever complained to me that my plugin is 200kb bigger because of ACF, or that they doing /somecommand took 0.0003ms instead of 0.0001ms
Eh
I'd pitch rewriting hypixel in Assembly if the guys ever accepted me
just check for "s" at the end?
am I part of most devs?
if it ends with an s
it should be "exodus' zombie"
then you add a '
check if it ends with "s" and yes, add "'". Otherwise, add "'s"
just so you know this won't work the way you expect
Illusion's - belongs to illusion
parent's - belongs to either parent
parents' - belongs to both parents
so getDisplayName is effected by nicknames just fyi, unless that is your intention
yeah
i'd just check for "x" or "s" at end, if yes: add one '
otherwise add 's
this will probably work in 99.99% of cases
yeah
but I'd also move this into an own method
e.g. getPetName(String playersName)
maybe you'll some day wanna add more stuff than just Undying zombies
if you can put something into its own method, then you should always do that
private final String TEXT_MASK = "xs";
public static String reference(String input) {
char lastChar = input.charAt(input.length() - 1);
input += "'";
if(!TEXT_MASK.contains(lastChar))
input += "s";
return input
}
^ is the "little shit that likes to use constants" approach
public static String reference(String input) {
if(input.endsWith("x") || input.endsWith("s"))
return input + "'";
return input + "'s";
}
is probably the most common approach
is it "alex' zombie" or "alex's zombie"?
I'm pretty sure that it's "alex' zombie"
This would be correct for possessiveness
box's color
box color
I'd say box's color
if ends with an s using ' only is acceptable
but the screenshot I sent says that it should be "Jesus's zombie"
you could also just do "Undying zombie of Alex" lol
This is also acceptable because it is a proper pronoun, really the only exception
if we're having a 10 minute argument over something this irrevelant, the plugin will be baller
the whole english language is fucked
make a phonetic parser
feed it through a neuralnetwork
and have consistently wrong results
or just make players enter a custom name for their zombie
Yeah I don't like it either. There is too many rules that end up being contradicted later and it was always upsetting the way they teach you in school
one year you learn something new
the following year, you learn what you learned last year isn't exactly true
exactly. and the pronounciation is kinda random at times
but german is also weird. we have random genders for every word
car is neutral, woman is obviously female, but the plural of "man" is also female
lol
for instance when you learn i before e, except after c So we learn this in school, but when you get to high school, you learn that this is actually false for so many things >>
yeah but there's so many exceptions to this
for instance neighbor does not follow this rule
exactly and it was annoying that what I was taught in school was wrong >>
seizure
i mean do names really count
getTargetBlockExact or something
How would I get a player variable based on their ign
Bukkit.getPlayer(String)
But you should avoid using igns at all. Always use their UUIDs where possible.
Well I am creating a command where you request to tp to another player using their ign, so I can't really use UUIDs
Player player = Bukkit.getPlayer(args[0]);
if(player == null) {
// send error message that this player isnt online
} else {
// teleport
}
sth like this?
or using ACF π
@CommandAlias("tp")
public void onTp(Player sender, Player target) {
...
}
ACF is such a time savor
Ok, so the whole chat formatting mess really has me feeling stupid rn.
Right now, I have a .parseColors() method that replaces normal color codes and hex colors (#rrggbb) with their ChatColor.of(color) format, and using player#sendMessage, it sends fine, colors and all.
But when I feed it into either TextComponent() or TextComponent.fromLegacyText(), the hex color formatting seems to just disappear.
Im trying to use components because in my plugin's config file, there are user defined strings that need to have (a pre-defined) click and hover actions, in addition to having both their normal and hex colors parsed.
This is my code: https://uploadi.ng/π§ππ€·π΄ [first screenshot attached]
and this is the output: https://uploadi.ng/π¦π₯ππ [second screenshot attached]
Can someone help me figure out how to parse the normal and hex colors from the config string, then apply click and hover actions to it?
try to use legacy hex color format and see if it fixes it
e.g. like this:
String message = ChatColor.translateAlternateColorCodes('&', "&x&f&f&0&0&0&0This should be solid red");
So doing that does let me send a red message (sending it with player#sendMessage()) but how do I then add hover and click actions to that?
When I use TextComponent.fromLegacyText(/* your example */),
it outputs an array of baseComponents ( https://uploadi.ng/πππ¦π ), so it seems like I can't just do message.clickEvent = blablabla
Is there some way to make TextComponent.fromLegacyText() not output an array? Or some way to merge the elements from the resulting array into one baseComponent or chatComponent
good question
I also had this issue once and I somehow solved this but tbh I have no idea how
lemme check if I find it
but to answer your first question: It will always return an array because it basically splits the string by colors
e.g. "&aGreen&cRed" will return two components, "Green" with green color and "Red" with red color
hm I don't remember in which plugin I added the click event but it's definitely somehow possible. Unofrunately I don't find it right now :/
@white root cant you just do stuff like this?
BaseComponent[] components = TextComponent.fromLegacyText("Β§cRedΒ§aGreen");
components[1].setClickEvent(...);
this SHOULD add a click event to the "Green" part
Actually, that isnt a bad idea, I can just iterate over the components, but again I feel dumb for not seeing a way of doing this, but how do I send that array of baseComponents to players?
Intellij seems to like nether player#sendMessage(BaseComponent[]) nor player#spigot()#sendMessage(BaseComponent[])
https://uploadi.ng/ππ§π
π
if you want to add a click event too the whole message, then you gotta add it to ALL the array elements
huh
sendMessage DOES take a BaseComponent... thing
maybe you missed it because it's a varargs method?
this is part of Player.Spigot
I'm not sure, Intellij seems to think im crazy for trying this
https://uploadi.ng/ππππ·
hm that is weird. In your screenshot, I can see that the second "suggestion" shows the BaseComponent varargs method
I mean, you're using kotlin, but normally that should work totally fine
The only thing that I can think of is that im building against 1.16 spigot api org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT, but even if I change that to 1.19, its still the same
what error message do you get when you try to compile it anyway, besides IntelliJ complaining?
nah that's no problem. this whole component thing has existed at least since 1.13 IIRC
wow that's weird. it literally tells you that there's a varargs BaseComponent... function
sorry no idea. It does work in normal java, as I showed here :/
what happens if you replace "val" with an explicit BaseComponent[] ?
I dont know much stuff about kotlin so no idea if this might fix it
like, try to explain to the kotlin compiler that "test2" is actually a BaseComponent array
(although normally it should know it already, so yeah, no idea :/ )
Ok, copying what you wrote, and having intellij translate it to kotlin provided a syntax that Ive never seen before, and put player.spigot().sendMessage(*components)
on changing my code to it.spigot().sendMessage(*test2), intellij doesnt complain, give me a moment and Ill see if it actually runs
oh, that's weird lol
it might have something to do with the fact that it has the exclamation mark in this method signature
that just means that it cant be null in kotlin, I think
So doing some research, that is kotlin's spread operator (since im a js dev, learning kotlin, I had tried using javascript's "...variable" spread syntax, but wrong format haha. -200 iq moment)
anyway yeah, using player.spigot().sendMessage(*test2) does indeed work
nice! Now you only gotta check if it actually works ingame, too π
It does indeed :dogekek:
oh okay, perfect
You have no idea how long I spent this morning feeling dumb trying to mess with kyori, spigot's chat api and bungee's chat api trying to figure out how to just send the messages I was formatting lmao
Anyway, tysm <3
no problem :3
im kinda surprised myself that I could help because I have absolutely no idea about kotlin lol
yeah NMS is a hell in some regards
what exactly are you struggling with?
"mob keys"?
hey y'alll, so i'm trying to code cooldowns and have no idea where to start, so i'd like a push in the right direction- like just the starting point and i can take it from there
i have a bunch of classes and i don't want to copy code too so i'd prefer to have a function in a class and reference it in other classes
Use unix timestamps (longs) and Maps.
First map each player to a CooldownContainer (A data class you write)
and then inside this container you map a String to a Long so you can
have named cooldown.
When an action occurs you simply check if the timestamp is in the future or past.
If you need a countdown or something similar then use a task that checks the timestamp
every so often against the current time,
hm
okay
so could i put this in a function in, lets say, my main java class?
and if so where?
i guess i could do a public static right inside the class
and could i use the config files for this?
i'm not good at SQL
unless i'm dumb and its not sql
Dont use any statics for this whatsoever.
Learn java and abandon the static keyword for a while.
The only things you can make static are constants like
public static final double PI = 3.14
Thats it. No more static for you.
ah
okay
public CooldownContainer cooldownContainer = new CooldownContainer(); would this work?
and then i'd make a new java class correct?
called cooldown container
The first thing you want is a CooldownManager
And you only create a single instance of this manager.
This manager manages a Map<UUID, CooldownContainer> with all the CRUD methods.
And every CooldownContainer has a Map<String, Long> representing the named cooldowns.
private final Map<UUID, CooldownContainer> cooldowns = new HashMap<>();
Yes this is a class. And you make it a singleton. This manager should only ever have one instance and then
you dont create another one. This instance should be in your JavaPlugin class and either passed through the constructor
of other classes or being retrieved by a getter.
Looks good
Important design note:
Never every create getters or setters for Maps, Lists, Sets or other data structures.
Never.
okay
soo
i'll start
wouldn't this technically be inefficient, according to this wiki i found https://www.spigotmc.org/wiki/feature-command-cooldowns/
Not its as efficient as it gets.
You can check timestamps millions of times per minute if you wanted and the server wouldnt even notice.
how would i tweak this cooldown in each ability?
You make the cooldowns agnostic. Dont think about which application will use them later.
Just make it modular.
Thats what the Map<String, Long> is for.
You will be able to set cooldowns for everything you want.
orr i could make a setter :))
(jk (?))
private final Map<UUID, CooldownContainer> cooldowns = new HashMap<>();
public static final int defaultCooldown = 15;``` i got this so far
i'm not rlly good at this
twt
The first line is useless
Yes of course.
What do you mean? Did you finish all the classes and methods?
If so then send them first.
uh
?paste
i'm sorry it's like 12 or so and i'm really tired, which classes and methods?
- The CooldownManager with all the CRUD methods
- The CooldownContainer with all the CRUD methods
CRUD=
Create
Remove
Update
Delete
https://paste.md-5.net/ejoxusavuy.java this is all i have so far
i'm sorry, i've only been coding plugins for about a week now twt
Ok so the cooldown manager only needs a single map for now.
Map<UUID, CooldownContainer>
Nothing else.
Then you add the CRUD methods.
Create the CooldownContainer class but leave it empty for now.
okay
i'm applying crud to the cooldowns
right?
so i add the player, remove them, then update the cooldown container then delete the map?
i'm sorry i'm half asleep
gonna try to figure it out tomorrow
thanks so much for the help
public class CooldownManager {
private final Map<UUID, CooldownContainer> cooldownContainerMap = new HashMap<>();
public CooldownContainer createContainer(UUID playerId) {
CooldownContainer container = new CooldownContainer();
cooldownContainerMap.put(playerId, new CooldownContainer());
return container;
}
public CooldownContainer removeContainer(UUID playerId) {
return cooldownContainerMap.remove(playerId);
}
public CooldownContainer getContainer(UUID playerId) {
return cooldownContainerMap.get(playerId);
}
}
aa okay
This is how your typical manager class looks like
Player joins -> create or load container
Player quits -> remove and save container
On runtime -> you get the container and use it
so in the playerjoin event i should run createContainer(pUUID)
public static CooldownManager getCdInstance() {
return cdInstance;
}``` in the javaplugin class
No statics
oh yeah
shush
cdInstance = new CooldownManager(); we instantiate it in the onEnable();
Yes. And then we pass this instance through constructors or create a getter for it.
i like getters SMH
just kidding i'm just using a template so i can't use a constructor here
CooldownManager cooldownManager = plugin.getCdInstance();
on join
UUID pUUID = p.getUniqueId();
String pUUIDString = pUUID.toString();
CooldownManager cooldownManager = plugin.getCdInstance();
cooldownManager.createContainer(pUUID);```
so this should create a container
it's for other stuff in the evetn
Oh god...
look, right now i'm using config.yml as a database
there's much worse stuff i'm doing than making a pUUIDString
so where does the Delete come in for CRUD
okay so how do i use this now
let's say... in my Mage handler
We are not at this point
One moment
public class CooldownContainer implements ConfigurationSerializable {
private final Map<String, Long> cooldownMap = new HashMap<>();
public CooldownContainer(Map<String, Object> map) {
map.forEach((key, value) -> cooldownMap.put(key, (long) value));
}
public CooldownContainer() {
this(new HashMap<>());
}
public void setCooldownFromNow(String name, long millis) {
cooldownMap.put(name, System.currentTimeMillis() + millis);
}
public long getCooldownLeft(String name) {
return System.currentTimeMillis() - cooldownMap.getOrDefault(name, Long.MAX_VALUE);
}
public boolean isCooldownDone(String name) {
return getCooldownLeft(name) <= 0;
}
@NotNull
@Override
public Map<String, Object> serialize() {
return new HashMap<>(cooldownMap);
}
}
Stay hydrated
back
okay do u mind letting me know what this does
cuz i really want to learn not copy code :/
Ok so here is the CooldownContainer. It implements ConfigurationSerializable so that you can simply throw it in your ymls
so i can put it into my config
ok cool
but i don't see anythign with the config in this code
This is the important code.
Ignore the rest.
A container can have many different cooldown timestamps.
They are identified by a String.
ok
ok first can you define a hashmap? i haven't done a deep delve into java yet so i'm not sure what it is :/
wait i can just search it up
oh
OH
so it's like the config file
but different
A map is a data structure which maps a key to a value.
You put in a key and a value and on a later point you can get that value by using a key
kinda
so i can just plug in my player's uuid into the hashmap and get their cooldown
pretty cool lmfao
Yes you get their CooldownContainer. And the container has a Map<String, Long>
So every player can have thousands of cooldowns. All you need is a name for the cooldown.
cooldownMap.put(name, System.currentTimeMillis() + millis);
}```
so what are we doing there
we're just inputting the cooldown into the HashMap?
hold on need more water
it's a really hot day lmfao
brain overheating
name is the name of the cooldown you want to set and millis is the time in milliseconds for this cooldown.
System.currentTimeMillis() returns the current time in millis.
In computer programs you will very often encounter the so called unix timestamp.
Its one number which started counting up at 01.01.1970 and will count for the next
couple of thousands of years.
This is how the current timestamp looks like.
You just have to think about 3 more digits at the end.
And this is the same for every computer.
You can think of this as a fixed point in time which is simply one long number counting the milliseconds
So
long future = System.currentTimeMillis() + 1500;
Is exactly 1.5s in the future.
so system.currenttimemillis gets the unix timestamp?
so what's the difference in doubles and floats? and why use floats instead of doubles? aren't floats just like half the size in bytes
same for like longs and ints, or ints and shorts
Imagine our current time is
50000
and our cooldown is
1000
Then we put 51000 in the map and every time something happens we check if the timestamp
is already over.
double just holds more precise fvalues
mkay
oh
double = double precision floating point = 64bit float
float = 32bit float
long = 64bit int
int = 32bit int
short = 16bit int
byte = 8bit
so it uses memory
i thought it jsut could STORE that much memory
so with this you can just choose how much memory to take up
thanks :)
nah, even a double d = 0 uses 64 bits
i get it now
its how much it reserves
oh
okay
yeayea that's what i emant
so @lost matrix in getCooldownLeft, you input the name and check if that time stamp has passed right?
and you return the amount of milliseconds left
and then in isCooldownDone you check if that cooldown is at 0
Yes. For example if the timestamp is 51000 and the current time is 50500 then there are still 500ms left
okay
you are REALLY helpful thanks so much for taking the time to explain stuff instead of just handing me the code :) it's really cool to do that
ok so next, we use these in runtime right?
Yes. I actually think we should add new methods to cooldown manager just for simplicity
okay
so these methods being?
hm
just tell me what they should do, i want to try doing them myself
public void setCooldownFromNow(UUID playerId, String name, long millis) {
CooldownContainer container = getContainer(playerId);
container.setCooldownFromNow(name, millis);
}
public long getCooldownLeft(UUID playerId, String name) {
CooldownContainer container = getContainer(playerId);
return container.getCooldownLeft(name);
}
public boolean isCooldownDone(UUID playerId, String name) {
CooldownContainer container = getContainer(playerId);
return container.isCooldownDone(name);
}
okay
Oh didnt read
its ok
just spoiler that
pwp
and i'll look at it if i give up
nvm i'll just not look at it
You basically just want easier methods for setting and checking cooldowns without having to always get the CooldownContainer.
So you copy the 3 methods into your CooldownManager
setCooldownFromNow
getCooldownLeft
isCooldownDone
And add a UUID parameter.
ok
i think i did iscooldown done
CooldownContainer container = getContainer(pUUID);
return container.isCooldownDone(name);
}```
i tried
did i get it right
oh
so i can just access the thing and return it
ok not that hard
alright so not that hard
thanks for letting me do it myself :)
okay so now
we can access this ONE instance of cdmanager
If you have all 3 methods then you are pretty much done
CooldownManager cooldownManager = plugin.getCdInstance();
at the start of each method i'd like to use it in?
Well you would want a field that store it
uh
it is in a field
CooldownManager cooldownManager = plugin.getCdInstance();
we're putting the instance into this variable
right?
or am i dumb
Example
public class SomeListener implements Listener {
private final CooldownManager cooldownManager;
public SomeListener(CooldownManager cooldownManager) {
this.cooldownManager = cooldownManager;
}
@EventHandler
public void onBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
UUID playerId = player.getUniqueId();
if(cooldownManager.isCooldownDone(playerId, "block_break")) {
cooldownManager.setCooldownFromNow(playerId, "block_break", Duration.ofMinutes(1).toMillis());
} else {
player.sendMessage("Sry but you can only break one block per minute.");
event.setCancelled(true);
}
}
@EventHandler
public void onPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
UUID playerId = player.getUniqueId();
if(cooldownManager.isCooldownDone(playerId, "block_place")) {
cooldownManager.setCooldownFromNow(playerId, "block_place", Duration.ofMinutes(1).toMillis());
} else {
player.sendMessage("Sry but you can only place one block per minute.");
event.setCancelled(true);
}
}
}
so the method you used was putting it into the constructor right? i'm using a getter
Well then you pass your JavaPlugin instance in the constructor and use the getter. Same result.
private final CooldownManager cooldownManager;
public SomeListener(YourPlugin plugin) {
this.cooldownManager = plugin.getCdManager();
}
CooldownManager cooldownManager = plugin.getCdInstance();```
heehee haha
i love getters
Thats static abuse and i can assure your that it will lead to problems
uh
This here is the only other solution i would allow
private final CooldownManager cooldownManager;
public SomeListener() {
ClassSystem plugin = ClassSystem.getInstance();
this.cooldownManager = plugin.getCdManager();
}
Well as long as you are not using getters in field initializers your are fine
import org.bukkit.event.player.PlayerInteractEvent;
public abstract class PlayerClassTemplate {
public abstract void onTrigger(PlayerInteractEvent e);
}
this is my PlayerClassTemplate
import classsystem.classsystem.ClassSystem;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
public class PlayerClassListener implements Listener {
@EventHandler
public void onInteract(PlayerInteractEvent e) {
ClassSystem plugin = ClassSystem.getInstance();
Player p = e.getPlayer();
String pUUID = p.getUniqueId().toString();
PlayerClass playerClass = PlayerClass.stringToClass(plugin.getConfig().getString(pUUID + ".class"));
PlayerClassTemplate playerClassTemplate = playerClass.supplier.get();
playerClassTemplate.onTrigger(e);
}
}```
and this is my playerclasslistener
its just that i have so many classes and don't want to rewrite the same code
is there any way to run my 1.8 plugin on a 1.19 server?
i also have an enum
if its set up properly, yeah
?1.8
Too old! (Click the link to get the exact time)
or do i have to change every variable back to 1.19
Do you use nms or craftbukkit?
Then there is no way to use it in any other version
massive bruh moment
should i be using NMS in my plugin?
now i have to switch from spigot 1.8 mappings to 1.19 mojang mappings π
no
or CraftBukkit?
its painful its complicated its messy
i don't use either rn
You really dont need it if you use newer spigot versions.
Its really only viable for very specific and quite complicated topics.
ah ok
In trash versions like 1.8 you have to still clutter your code with a bunch
of garbage nms to use even the simplest of approaches.
Btw dont use configs on runtime
When a player joins -> load all data from the config into classes
when he quits -> save all data from the classes back into the config
"demeters_saturation" can you use _'s in the names of cooldown containers @lost matrix
hahahahahaha this is how i store my player's class
wait
but why not
You can as well just use "$%&Β§ BLib_ -- Blob ##Γ*" if you wanted to.
Its a String.
sure
More context. Im assuming that your backend runs a newer version and that you use viaversion and viabackwards?
@lost matrix thank you SO much for the help today :)
uh- actually it's really buggy
Show some code
https://paste.md-5.net/uficiyokoh.java here's my entire Cleric class
I am not reading that mess
fair
I have not doubt that this is buggy has hell and that you will have to debug this for weeks
man.
You should extract this into like 5 different methods
https://paste.md-5.net/rehatamili.py this is all the code that actually uses the cooldowns
well at least one of the abilities
owo
Looks fine. Nothing wrong with this section
hm
https://paste.md-5.net/iyilotomub.java this is my class system, it was basically copy pasted from you so it shouldn't have any bugs
Each of those should be in their own method
You can mark the lines, right click -> Refactor -> Exctract Method
waiat damn
coool
ok
so now
https://paste.md-5.net/kiyetitija.java is there anything wrong with this?
did i make a mistake with anything
OH WATI
so you see the long on the 2nd method
that's not supposed to be caps right
all lower case
okay
i got it
pls work
doesnt really matter
in which class?
yea that's the one i was talking about
okay so when you do an ability you can spam it until the cooldown runs out
so its like wierd
weird
Oh yeah this method is wrong
public long getCooldownLeft(String name) {
return System.currentTimeMillis() - cooldownMap.getOrDefault(name, Long.MAX_VALUE);
}
Should be
public long getCooldownLeft(String name) {
return cooldownMap.getOrDefault(name, 0L) - System.currentTimeMillis();
}
In CooldownContainer
oh
okay so what's the difference
oh
dOSHFp
OH
i got it
thanks so much
pls say it works
FRICK YEAH
thanks so much smile :)
nice
hm its still acting a bit weird but it's way better than before
so milliseconds are 1/1000 of a second right?
so 5 seconds would be 5k milliseconds
right
then why is the cd of one of these 50 seconds and the cd of the top one is like .5 seconds lmfao
https://paste.md-5.net/yoporoyini.cpp (this is what activates the command if it's any help
Sysout the modifier
it should be 1.0
yep
[22:55:26 INFO]: 1.0
[22:55:26 INFO]: 1.0
[22:55:26 INFO]: 1.0
[22:55:27 INFO]: 1.0```
BRUH
java version isnt switching from java 8 to java 18
changed the environment variables and stuff
still stuck on java 8
go into terminal and type in java -version
did
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
Just install the latest jdk then
Get the installer. It does everything for you.
I removed the de edning
yeah
miss the good old days when you spent hours debugging stuff and did everything by hand rather than an application doing everything for you
Can do it all by hand if you like lol
intelliJ users
cloud explain me what this color says?
the getSeconds
why its colored that way?
Deprecated
Hovering it should tell you too
It says the method is in void
No the method just deprecated
so deprecated stays for in simple english?
i cloud google it yeah guys but i want an human being explanation
Deprecation means this method is about to be removed and should not be used.
In almost all cases there is a better alternative for that method already implemented.
oh
Read the docs for the method to find the better one
so the hint it shows me is the better alternative?
Well it might if you have the documentation for it
the other thing showed the same thing
ill just not give it attention might Date be outdated a bit
but its fine
i dont see a reason to switch it if it works it works
thanks alot from what i understand its basically the out dated shit π and it pretty much tells me listen we not gonna support it in the new versions so stick to what we suggest instead
Deprecated code should always be avoided if possible. Its very possible for you so avoid it.
yeah i have so many ways to get correct second
What do you need?
The current second in which context?
I dont understand. There is no "current second"
System#getCurrenrMilli
yeah i dont need it
Unless you are speaking about the unix timestamp
Lol u make no sense
Whats your goal? There is 100% a better approach.
i already think about making own timing system instead of comparing time...
so ill just make in the data class an integar that will be timer
i just make a player select a block and be able to execute commands
now i was thinking to make a timer to remove him from the block
Your making a timer? Why not just use a ticker for a timer seems nonsensical to use much else isn't that how timers work after all?
instead of checking if he is near all the time
Read from here. I explain the best possible approach for timers and cooldowns in great detail.
Alternatively if you don't need per tick updates just compare current millisecond timings
but i cloud update it anyway ;/
if he selects a different door the hashmap will replace it
each time
Cloud update it? Wrf
Always compare timestamps. Never ever manually update a timer.
Its an absolutely horrible idea.
Bruh don't be storing your timer in a database lol
i dont store in database
i store it in hashmap you told me to make own objects to store locations
so why dont i make either a timer inside of it and update it
I think it was a mistype of could
Mf I'm dumb
why?
Ill just say this one more time and then im off to sleep.
Dont manually increment a timer
Its a really really bad idea. Worst possible performance.
Most possible code fragility and worst sync issues.
you understand what i mean now?
i do decrecment timer and == if equals
remove from map
why its terriable but if i need update value each time
what you do compare if value is >
and if remove and allow
I dont have the willpower to deal with this right now.
Read the message ive posted above. It has a bunch of code you can read through and utilize.
can i use 1.19.2 nms plugins on a 1.19 server?
?tas
I believe itβs all the same NMS version
depends how
i dont think 1.19.1 and 2 added something relating to nms?
Depends you'd have to check
Idk you could try and see if it works
yeah except i cant π
I'd say maybe
I mean nms mighttt work across version maybe depending on what you use though I thought those classes couldn't be referenced cross version no Matter what
My best advice would be to try and see
another help
Unresolved dependency: 'org.spigotmc:spigot:jar:1.19.2-R0.1-SNAPSHOT'
using nms
damn not gonna read his explanation to the guy who learn java yesterday
ill better stick to ways i know
damn
lmao
im not about it if u look up u will get it
what
but 7smile7 tells me to take a look at his high performance cooldown util or what ever
now i dont believe u can check 1 million times and server wont feel
will do a layer 7 attack on the cpu lmao
now in general it will do maybe a really small perfomrance tweak that maybe doesnt even worth the attention
i know an guy which converts UUID into binary
you know how efficent it will be
if you store 1 million UUID in binary instead of the normal way
it will save you 10 mb's
so sometimes those performance tweaks are dogshit and thanks god i pay for dedicated server and not for shared hosting with half theard lol
What
would ServerPlayer#displayName = "balls" set the serverplayer's display name to balls?
Yes
how do i set location of a serverplayer in nms mojang mappings
im wondering
where i put those x,y,z for god sake
that what my mind told me
not sure if its the right that
gonna just try it..
Iβm trying to make a countdown system but Iβm not sure how to go about it. Iβm using a runnable and Iβm trying to get the counter value that increases whenever the runnable is running
Code:
new BukkitRunnable() {
// active for 30 secs
// To Do, have a getter for counter?
private int counter = 0;
private int maxCounter = 30;
@Override
public void run() {
// if game end
if (counter == maxCounter || playerQueueStatus.getQueueSize() < playerQueueStatus.getMinQueueSize()){
cancel();
Bukkit.broadcastMessage("" + ChatColor.GOLD + ChatColor.BOLD + "Game Ended!");
}
counter ++;
}
}.runTaskTimer(plugin, 0, 20);
}```
Unfortunately itβs not as simple as creating a getter inside the method.
move your counter outside the runnable
btw if you're creating a game mode, it's easier to have one task running and put everything in it
Yea thatβs going to be the main runnable for timing stuff
You put it out into the class?
Hey, How can I get this part of a player inventory?
Yes, in your Game instance save those counters, and other variable you'll need in the runnable
In my plugin, I serialize data with gson. I have to use a custom-type-adapter, but how do I write one for a map?
Player#getInventory and these are slots 0, 1, 2.....
Yes I have this but then I get a player inventory, if I cast it to inventory, it return only the 4x9 items?
What happends after e.setCancelled(true);
does it finishes the code after setting the event cancelled
Why do you want to cast it as Inventory ?
any other code you have after that will run just fine
that event will just be set to cancelled and will not happen
even other events listening can still listen to it
I need to storage and load it from a db, then I used the inventory because I can use Bukkit.createInventory(...)
Can I do this with player inventory?
Well how do you save Inventory ?
because it works the same : just save for each slots the item it contains
I tried it but I realised that because I was running the scoreboard timer in another class, I had to create a new object so the counter it returns wonβt update because it is different
Any ideas?
the editionNumber part
We told you what the issue was yesterday π
I was told to do the id and I did
?di
Guide to dependency injection: https://www.spigotmc.org/wiki/using-dependency-injection/
wait lemme check
checked da github?
yes
alrighty guess im more drunk now
also is there some kind of rule saying that u shouldnt have more than 1 extends java plugin thing
wait isnt super. a nms thing
That's a Java thing
You can't have more than one main plugin instance per plugin
ah
public HashMap<String, Integer> theBackSlot(String s, int i) {
new HashMap<String, Integer>().put(s,i);
return HashMap<>();
}```
I want to do something like this
everytime method have been called it will create a new hashmap and add the parameters in it and will return it
how can i do that
Why would you do that
Complicated
To me it looks like you don't want to use hashmaps
Β―_(γ)_/Β―
but i am trying to control which slot, player have been came
Is the slot key or value?
When creating a custom entity, I saw that you use the initPathfinding() to add new path finding goals. How would I do that with Mojang Mapping? Also, if there's a doc site where it shows what everything does, it'll help a lot
Value
Yeah registerGaols
Δ°magine an inventory has sword, food,block, tool categoires and i am clicking one of them and saving the name of them such as if its sword saving the "sword" string and the slot sword is on.
I'm trying to make a minigame timer, however when I added a static to the values that increase in the runnable, every time I activate the runnable, it sends the time left on the countdown one more time to the player.
static int maxCounter = 30;```
doing cancel; stops and deletes a runnable right?
It's easier to create a single runnable that loop for a the game long
instead of creating multiple
but yes cancel stop the task
Hmm if thatβs the case, it canβt be that I have runnables that arenβt stopped
So Iβm confused why it is outputting the countdown more than once
?paste your code
Is PluginMessageListener working as async?
few remarks:
- your class seems to be an object, so why putting the counters static ?
- you should to early returns to better understand your code
- can you please explain more clearly what's your problem ?
If I donβt put my counters to static I canβt access them from the other class where I am managing my scoreboards which would display the time left as I have to make a new object for the scoreboard managing class
Guide to dependency injection: https://www.spigotmc.org/wiki/using-dependency-injection/
and why separate it ? call it directly from the game task
And the problem would be that the debugtimer method that sends the player a message would send it again to the player after the first time the runnable is activated. Increasing by 1 time it would send to the player again after every time the runnable is executed again
that's what i said. creating multiple tasks makes it a lot harder to manage.
you should definitely have only one task that you don't stop
java.lang.IllegalArgumentException: x out of range (expected 0-15, got 27)
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:193) ~[guava-31.0.1-jre.jar:?]
at org.bukkit.craftbukkit.v1_19_R1.CraftChunk.validateChunkCoordinates(CraftChunk.java:362)
at org.bukkit.craftbukkit.v1_19_R1.CraftChunkSnapshot.validateChunkCoordinates(CraftChunkSnapshot.java:171)
at org.bukkit.craftbukkit.v1_19_R1.CraftChunkSnapshot.getBlockSkyLight(CraftChunkSnapshot.java:106)
at me.entity303.tramaniaclasses.listener.BlazeListener.lambda$new$2(BlazeListener.java:64) ~[TramaniaClasses-1.0-SNAPSHOT.jar:?]
at org.bukkit.craftbukkit.v1_19_R1.scheduler.CraftTask.run(CraftTask.java:101)
at org.bukkit.craftbukkit.v1_19_R1.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
ChunkSnapshot#getBlockSkyLight returns 27?
How exactly am I supposed to feed it with an x of 27 while reading data? π
if (chunkSnapshot.getBlockSkyLight(
all.getLocation().getBlockX(),
all.getLocation().getBlockY(),
all.getLocation().getBlockZ()) >= 15)
Oooh
Ops
Sorry, my mistake π
Thought it was returning a light level of 27 for some reason
Now it always returns 15, no matter what...
Tried one block below, tried one block up, nothing
You are working with a snapshot. Its not going to detect changes
the light level will be whatever it was when you took the snapshot
Yes, I'm taking the snapshot after the change though
15 I belive is direct sky light
Yes, I blocked any light, so it should be 0
This is where it is supposed to check for the sky light
It's completely dark, as you can see
You're inputting a location x y z into a chunk location
First get the chunk of the location
Take your x y z modulo 15
And get the result
why tf does this always happen
why can intellij not understand that its the sources root folder
without me marking this explictly as sources root
I mean its in src/main/resources lol
erm
X: 12
Y: 2
Z: 5
I meant src/main/java
?paste your code
you can;t be checking the block you think you are
It is.
I placed a sand block and checked the Material
Any better alternative? π
(I pretty much tried to reconstruct the nms check for "IsInRain")
Why do you need it ?
Just put your variable inside the task
Try to test the SkyLight outside all of your code
why the fuck are people calling their player variable 'all'?
Can i make a web proxy for my spigot plugin?
unless that player's called All it doesnt refer to all the players
Like to a BlockPlacdEvent and get a sky light
To remind me that I'm looping through all online players π€
Okay, jokes aside, I normally call it just player, not sure what happened here π€
π€
it's fine if you loop over all players I guess
for(Player all : Bukkit.getPlayers())
this is fine to me
So... A normal variable instead of an AtomicReference?
If I do this, I won't be able to compile...
take a better naming convention then and call it yoMama
I think allPlayersInAForLoopLoopingThroughBukkitGetOnlinePlayers is a way better name
And makes totally sense
create a wrapper class lmao without all that atomic shit
But.... That would be work π¦
I mean... I could do that, but would it make any difference? π
expression parser progress meh
yes
Before trying to improve the code, try first to do a dumb debug test of the ChunkSnapshot
Create a BlockPlaceEvent and try to get its sky light level
i dont get why people call atomic "shit"
Without creating loops, and tasks or whatever
I mean, what's the problem in using it?
They're not. But in this case it's really useless
or search the snapshot for ANY block thats not level 15
its shitty that you have to use that instead of assigning a variable within a lambda expression
It does find a few
then its down to how you are checking. wrong chunk, wrong coords or something
All of these blocks are at chunkX 4, way up in the sky and chunkZ 12 π€
are you certain there is a block above where you are testing?
And none of the tested blocks exist, all of them are just air
I'm literally encased in dirt blocks, no light whatsoever
you just said no blocks were there, they were all air
Let's try checking the light when placing a block
I made a loop going through all blocks in the ChunkSnapshot and printed all blocks which have a Sky Light level lower than 15, it only finds a few air blocks
Yes
ah yes, "half life" icons lol
@EventHandler
public void onPlace(BlockPlaceEvent e) {
e.getPlayer().sendMessage(String.valueOf(e.getBlock().getLightFromSky()));
}
This prints the correct value
But ChunkSnapshot doesn't
yes, the block hasnt been placed yet
it only gets placed after the event was called
actually I believe the block place is an odd event, it is placed and if you cancel the event it undoes the placement.
If I'm remembering correctly
I just tried to find that part of code but I cant find it lol
It's dark magic. It exists but doesn't really exist
Hey
I am trying to fill a chest with items but only at the center
but I can't manage to make it not to fill the right side
public static ArrayList<Integer> getIndexes(int amount) {
ArrayList<Integer> indexes = new ArrayList<Integer>();
int index = 0;
while (indexes.size() <= amount) {
if (!(index % 9 == 0 || index >= 0 && index <= 8 || index >= 45 && index <= 53)) {
indexes.add(index);
}
index += 1;
}
return indexes;
}```
amount is the amount of items the chest is going to have
check if (index + 1) % 9 == 0
Okay, tested it 3 seconds after the event, but it still says 15.
So ChunkSnapshot is definitely broken if it comes to SkyLight π€
if yes, it's the right side, I think
Index % 8 == 0
I dont think that would work
Since sides are multiples of 8 and 0
it would return true for the 16th slot which is not on the right side
Oh yeah also 9
Let's just skip the light test then π€·
Works just fine without it...
index % 8 for right side and index % 9 for left side
Indeed
tbh I'd just hardcode the borders as quick fix lol
My brain doesn't want to work today
i usually have a MenuPosition class that uses int row and int column
so I can just check if column is 0 or 8
?paste
That's quite the same actually
yeah but it's easier to work with an actual object instead of "raw slot numbers" imho
now I have this error
[14:22:44 ERROR]: Could not pass event InventoryClickEvent to EcoEnchantsInterface v1.0
java.lang.ArrayIndexOutOfBoundsException: null```
Show the code again pls
...
if (!(index % 9 == 0 || index >= 0 && index <= 8 || index >= 45 && index <= 53 || (index + 1) % 9 == 0)) ...
yeah code like this is horrible, why not just wrap the slot into some kinda object
then just check if the column is 0 or 8
Or add a index > 53 in your ! Check π
I hate slot numbers
arent there also numbers for the crafting grid?
i dont know, I made this for angelchest which doesn't care about the crafting stuff
oh cool
but yeah IIRC the crafting grid is 41-44 and the result is 45
Why not like
for(int i=10; i<37; i+=9){
for(int j = i; j<6; j++) {
setItem(i+j, item);
}
}
Might be wrong cuz I'm on phone but something similar
If that is considered "center"
I'd still just do it like this π
for(int i = 0; i < inv.getSize(); i++) {
GUIUtils.MenuPosition pos = GUIUtils.slotToPosition(i);
if(pos.getRow() == 1 || pos.getRow() == 6) continue;
if(pos.getColumn() == 1 || pos.getColumn() == 9) continue;
// Do stuff
}
I hate to work with slots. Simply do the following.
int slot = ;
int x = slot%9;
int y = (int) (slot/9);
int slot = x + y*9;
This is making it so much easier
bukkit's inventory api sucks in general
is there a way to set an entity or a player to a riptide state?
yeah that's basically what my MenuPosition class does
is it gonna be null? is it gonna be Material.AIR?
who fucking knows?
yah
if I have 0 air, then it's not actually air, I guess?
I could understand it if it at least would be 1 air
but 0 air?
Ig nothing would be a better name
how do I check if an int is inside
private static int[] illegalSlots = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 18, 27, 36, 45, 17, 26, 35, 45, 53, 46, 47, 48, 49, 50, 51, 52};
```
Use a Set, it's slow to check an array
Otherwise Arrays.binarySearch(array, entry) >= 0
E.g. Set<Integer> illegalSlots = new HashSet<>(Arrays.asList(0, 1, 2, 3, ...));
probs want an immutable set
new HashSet<>(list) will make it mutable again right?
yes
but why put it into a set in the first place
i mean it will only ever have like 8 entries or so
trying to over optimise
yeah it's a waste of time to even think about "is a list or a set better" lol
What better a list or set?
in this case: both are equally good
I always make that question
if someone really wants to overoptimize this, then just use a switch case
:concerned:
lmao
i guess this would indeed be the fastest way
What the best way for disabling a logger from another library?
For example I want to disable JDA logger
Because its really painfull to see that ugly Messages
logback.xml
with this, JDA only logs "info" stuff (and higher, like WARN and SEVERE) while my own stuff also logs "debug" stuff
I cannot do that
Because im using it as maven dependency
π¬
Also why the heck Logger.getLogger("paxkage.logger.Class").setLevel(Level.OFF); doesnt work with JDA when with mongo works perfect
Sometime java coding its really weird
I feel like turning off logging is just a bad idea in general
How could I get a player to be able to use a bow even without arrows in their inventory? is that possible or is that fully client side?
I would think that would probably be clientsided; might be a way to do it with packets
You can launch an entity arrow
personally when they rightclick with the bow I would just give them an arrow and cancel the event when done
JDA uses Log4J, you can do Logger logger = LogManager.getLogger(JDA.class)
Oh thanks mfalex