#help-development
1 messages Β· Page 779 of 1
excatly
@eternal night hey bby <3
stranger danger
Holla miles 
telling me to use a memory leaker pfft
yeah lynx knows my IRL name
@echo basalt werent u the guy with a pretty nice questing system
could i uhh take a look for educational purposes of course hehe
I don't remember illusion having a good quest system or making one lol π€
fuck you it is decent
lol
This is the idea
or well
if you want it to create in code you do it like this
I also have a parser
im mainly interested in how you handle the objectives
read this
and this is the uh
walk blocks objective
in minestom
I can't bother opening the spigot project
code is the sae
promise
getProgress is our stuff
yea thats enough i see the idea
we use it on menus n such
It can leak at times but usually it's not an issue
what are the cases that it could leak
if we knew it would be fixed
oh lmao
when theres a hole in the bottom
but like how often is it
very leaky
I've never had an issue with it myself
I can't seem to get the item that the killer holds under PlayerDeathEvent. It just prints out an empty string. Anyone knows why that might be? I tried getting the inventory of the killer and then getting the mainhand item and then getting the itemmeta so I could get the item displayname itself:
Player killer = e.getEntity().getKiller();
PlayerInventory killerInventory = killer.getInventory();
ItemStack item = killerInventory.getItemInMainHand();
ItemMeta meta = item.getItemMeta();
plugin.getLogger().info(meta.getDisplayName()); //this becomes empty output
Gradle is pain
it should be noted that Olivio has a lot of ram at hand too π
jk, have no idea how much ram they have or use lol
yo frosty
so what does the mc plugin even do, doesnt it just setup the files for u?
I managed to get a few messages pinned
nice
how can it be a memory leak is what im tryna nuderstand lol
are you proud of me 
wait ur irl name isnt y2k_
It does a bit more than that. For example it helps a lot when working with Mixins
my life is a lie
I got one problem, after like 2 messages of showing cooldown it pretty much doesnt work anymore, can 2 runnables not run at the same time?
no unfortunately
its really good. Making more of a name for yourself. Eventually everyone will know you π
yeah
it also validates your plugin.yml for requires fields.
not that you trust me
I also managed to schedule a meeting with a chick from some gaming company at the tech conference
it's some esports media org
pfft blocked
hahaha
they got media passes :)
interesting
they said something about a collab, can't wait to break it to them that I make minecraft ploogin
I mean if they really are a media org, then this shouldn't be surprising lmao
It'll probably be fine I can just give them my youtuber contacts
nvm I merged them into one scheduler and works now, no spam and shows a number
but can 2 schedulers work at the same time?
The home of Spigot a high performance, no lag customized CraftBukkit Minecraft server API, and BungeeCord, the cloud server proxy.
yes
and what happens if I try to invoke scheduler thats in the middle of run?
using a scheduler for cooldowns isnt the best
instant 
bro
What did instant do to you
made an instant instance of instance
https://www.spigotmc.org/wiki/feature-command-cooldowns/ either way 2 or 3
The home of Spigot a high performance, no lag customized CraftBukkit Minecraft server API, and BungeeCord, the cloud server proxy.
the life of a developer
^ one of the reasons I've never properly published a plugin
^
My main reason is making the resource page
wait till you realize you need to delete half the plugin
because the way you went about it was flawed or dumb
I just cba to make it look decent, but I refuse to publish a plugin with a shitty page
I always start a project stay focused for a week then move on
When I come back it's a mess so I start over
repeat
me all the time
y2k
why is runnable not good for cooldowns
or if you have a plugin like one I have, you have to basically recreate almost everything in it XD
I've had to trash my multiblock structure system a few times already
the server doesnt always run at 20tps
wat
hows ur gen plugin coming along
pain I hate multiblock structures
idk
that was for y2k
still dk
Tf is a gen plugin
but the server doesnt always run at 20tp so the runnable doesnt run for a tick
does #3 need dependency?
no
it generates resources over time like pretty common with skyblock sept literally ever generator plugin ticks all of their generators instead of doing everything lazily
Define lazily
me doing anything
well you don't need to tick you can just calculate on interaction
much likes signs cough merge my PR md5
Do signs tick??
yea
what classes should i check out to understand how to achieve this
π but why
y2k i will turn you into an inventory in a minute
mojang doesn't know how to code ig
How does one interact with a generator
Donβt they normally just spit items on the floor
right click
or command since mine can be done virtually
its an Inventory GUI usually
in case they change of course, or when you use them to build trap floors
md5 merge my other pr
Wouldn't that just be handled by block updates
we can't merge that one it would break everything
everything they do on tick can be done lazily signs don't need to tick
it was just a dumb oversite I assume
was more sarcasm then anything lol, they shouldn't really need to be ticked
but they do because mojang
Anyone know how I can make a respawn packet using protocolLib (1.20.2)? or atleast what I need to set?
skill issue
Player#spigot.respawn()
you don't need protocol lib to respawn a player
speaking of Player.spigot().respawn() that should be merged in CB
Component and ItemStack
CraftItemStack too
people never know it exists because who tf looks at the Spigot interface docs
I do o.O
^
A more realistic question is why its in spigot vs cb maybe that method is that old
Technically im not really respawning them, I want to send a respawn packet to update their skin and stats, and I already have this whole packet system so...
ahhh
You can always capture a respawn packet and take a look
there is a specific packet for this that doesn't respawn them
Rlly? Whats it called
Yeah was gonna do that after looking around
I already send a PlayerInfoUpdate Packet but to my knowledge you still need to send a respawn packet so it updates for the rest of the players
Especially when modifying info like their skin
Only the one I modified
Try sending it to the other players too
alright
ok lol for some reason opening craftitemstack makes intellij freeze
ok what the actual fuck could possibly be causing this its so unfathomably random
happens when it tries to decompile a shit class, i.e. Material
doesn't need to decompile if you provide sources
if I have a bunch of custom items and I dont want each one to "identify itself" how would i go on about that
so for example on a right click event I dont want each custom item to filter the event
considering it freezes upon opening for them, that's probably not the case
you can make a listener for every possible item type and call a custom event
that's pre-filtered
illusion do u rem what I had before?
it was the interface with empty default method bodies
you've been bothering me with this for ages
just make a bunch of custom item events
maybe ill just use the bukkit event api
is the code any okay? minus the bukkit runnable ill try to change it for something different
That will break as soon as there's more than one player
why
or are you registering a listener per player
you can do that?
Yes but don't
so what do I do
can I just edit config for playerstats and add this cooldown here
That would be a bad idea
but learn what exactly
Here are some links to get you started on learning Java:
- https://www.codecademy.com/learn/learn-java
- https://www.sololearn.com/learning/1068
- https://www.learnjavaonline.org/
- https://programmingbydoing.com/
- https://docs.oracle.com/javase/tutorial/java/index.html
The last one is the only official one, however some of those concepts assume that you already know a bit about programming. https://media.discordapp.net/attachments/694661573125472256/998143126373941248/6n0v4g.gif
https://dev.java/learn/ is also a good start
I mean Java's a country if I'm not mistaken
Looks like it was registered/managed by oracle
choco are you enjoying hpyixel
Just doing some onboarding. I probably won't start actually making anything until next week or so
:,)
add death run thanks
yes yes death run much player fun yes
island in indonesia p sure
I dunno where it is, I just remember it existing Β―_(γ)_/Β―
people told me here its fine if I learn at the same time as I write plugins, going into most likely a 50hr+ course just to stare at console to see if the output is the one I wanted is pretty dull
its fine to learn java with plugins but you need to atleast know the basics before making plugins imo
The idea is to master the basics so you actually understand what people are talking about when they help you
you know a person throwing tutorials that they most likely havent even seen themselves to judge if they have said fundamentals isn't super helpful either
and like, someone here also said that fundamentals are subjective
well
so more or less id practically never get fundamentals by everyone's definition of them
let's just say
everyone wants to help
But not everyone is qualified to help type deal
Just listen to what the "regulars" say and you'll be fine
and don't take everything literally
Sometimes people just BS their answers
maybe i can help you
what exactly are you looking for?
so if I want to make player specific listeners can I somehow loop for them?
im sorry but im not advanced enough, but maybe i can find a different solution, what exactly are you looking for ?
it was general question not reply to this
dont make per player listeners
how about HashMap of UUIDs and cooldown values?
look at the cooldown manager tutorial i sent it shows how to have per player cooldowns
there you go
cooldowns with a hashmap are a great idea, are you familiar with System.currentTimeMillis?
not really
with System.currentTimeMillis, you are getting a long representing this particular timestamp
HashMap is like dictionary?
?
Yes
or like kind of PDC where you have "something" = value(can be int, string etc.)
yes every key has a value in a hashmap
yeah you dont need runnables for cooldowns
Here we go again π
I spent like 2 hours figuring out how they work
they are still useful tho
Time for another rewrite
what are Runnables useful at?
Running things in the future
for example saving data every few minutes
or sending a message like join our discord every few minutes
can I make my plugin run my own commands?
yes
thats useful
or just running things on a consistent basis
you dont even need runnables forr that
Bukkit.dispatchCommand
dispatchCommand is fun to mess with sometimes
er I'd avoid that if possible
well yeah
ideally you shouldnt ever need to run the command like that
honestly its kind of frustrating to hear "learn fundamentals" and assuming that I didnt even read anything, but I did entire w3schools course and so far utilized maybe like 70% of what I learnt there
like bro I am not going to recognize shit at the speed of light π
in my opinion you should just work on what you want and google or ask when ever it doesnt work
well, the best way to understand the fundamentals is to use them in something so you have an understanding
there is going to be plenty of things though that can't always be explained in a very basic way, like for example keywords
there is going to be plenty of keywords that you won't know when you should or shouldn't use them because there really isn't an easy way to explain them except what they do
for example, the difference between private, protected and public
it can tell you what those do, but not when you should or shouldn't use them
and there is even more keywords then those, just those are the most common you will deal with π
transient
I never used protected lmao
anyone got a better method name than this
static <T extends RegistryKey> MutableRegistry<T> newMutable(Supplier<Map<String, T>> data) {
Method creates a mutable registry, but I really hate this method name for some reason
I wouldn't call it Mutable that is for sure
ahh fair
what do you think is a better name Cuz Registry and AbstractRegistry were already taken
just a template
I'd call it Gustavo
fring?
Or Caroline
only difference between this an my FrozenRegistry is that it can be registered too after created
so an updated version?
well it can be updated
Should I do like UpdatableRegistry
I'm trying to make my new plugin completely data driven so I have quite a few registries
wait how is it not initialized if its already been initialized in constructor
that is outside the constructor
it will get init'd before the constructor runs
you got sent something for just that earlier
oh like that?
yes
okay I think I got it
so I basically made my main class only around setting up commandexecutors and registering events and parsing plugin instance further and each of my class grabs necessary instances of utility classes or plugin instance like that with initializing fields and then giving them values via constructor, is that a good way of making it?
to clarify, if you look at DamageManager. The way you have declared it will make it not initialized just declared. If for some reason BoneAbility is not invoked, DamageManager will be left unitialized. Most times not an issue, but it could be say if another method below that BoneAbility method needs it but is say static. Now if something outside of the class access that static method, DamageManager would be unitialized. You can intialize stuff at the top where you declare and generally if you are able to initialize that early its best to do so. Its fine the way it is right now, just something to be aware about.
is DamageManager initialized in my next 2 screenshots by main class?
A class being initialized isn't the same as a variable being intialized
two different things
declaring a class is basically writing it down while initializing is making an instance out of it?
or do I get that wrong
also you can have 2 instances of a class but they both be different unless you have something in place to ensure only a single instance also known as singletons
anytime you do new DamageManager(plugin) you will get a new instance of the class
but now lets take your variable for example
yeah this class has both utility methods for counting damage and has event listeners that listen for player damage to mobs, so those listeners would only be initialized by instance made in main class, while other instances would just be using utility methods?
DamageManager damageManager = Rpg.DamageManager(Rpg) now if you had a method in your main class Rpg named DamageManger, and if it returned a DamageManger Instance. Instead of the variable creating an instance, we have now deferred to a method to create or return an instance instead.
yeah I dont get that
at the same time if this was at the top of the class, the variable is also now intialized regardless if DamageManager method returns anything or not
well at minimum, it has to return a DamageManager object, but that doesn't necessarily mean the object isn't null
the reason I can use Rpg, is because all main classes of plugins are static, therefore you can directly call the main class. Anything that is static can be directly called. Your main class also extends JavaPlugin, so it makes a valid Plugin object due to inheritance. Hence I can just stuff that into the constructor
yeah I get that
I dont need instance of Rpg class
I can just get plugin from it
and pass it via constructor
well it may be handy to intialize your plugin instance before the constructor
but, at least you are getting the hang of it regardless
like this?
private Rpg plugin;
I typically keep a static method in my main class
so I can do something like this
private Rpg plugin = Rpg.getInstance()
then you don't need a plugin instance passed via constructor, handy when its not needed to do so
like true utility classes for example
Probably the better practice generally speaking
a singleton here is fine tho like frostalf is mentioning
but generally what im doing is not as bad?
no, its correct
Just instead of using JavaPlugin however
which is the more generic version
you should use Rpg instead
use JavaPlugin if you are expecting an object from other plugins
What about JavaPlugin.getPlugin(Rpg.class)?
That makes no sense to do even though it would work, you would use such a method like that when you want to fetch a Plugin instance of another plugin
not your own lol
its fine, if you cant be bothered to write ur own singleton then use that
Altho it goes through the classloader and some other stuff
U also have getProvidingPlugin
Which is really nice for libraries
As frosty said, prob doesnt make much sense if u need to call the getPlugin one tho lol
I think making intelligent use of dependency injection and structural decisions will allow me to avoid using a singleton altogether
is it an okay way to make use of utility classes that dont need plugin instance and those that need plugin instance to work?
That presupposes that singletons are inherently bad regarding design
They are not
Which is a wrong assumption in the first place
Singletons have their place just like any other design pattern
Yeah go to sleep
Yes, but one should not throw a singleton at every problem that would allow having one just because it is "easier"
a true utility class you wouldn't intialize the entire class. They typically have static methods with a private constructor for the class that prevents an outside source from intializing it.
So because you wouldn't have a constructor to intialize, it makes sense you need a different way to fetch a plugin instance
Of course and then its also the fact that singletons rarely make ur code easier anyway
which is what I was essentially inferring to
the private Rpg plugin = Rpg.getInstance()?
well, that is just an exception to the rule because main classes of plugins are singletons and static
but yeah
so to turn it into a static class I'd have to make private constructor and static methods?
well to make a static class, it doesn't need to have a private constructor. I was stating in terms of conventions if it truly is a utility class, then the methods should be static because a utility class itself shouldn't need to be initialized. You could make the class itself static but generally not necessary unless its a functional class then probably wise to do this
Iβd say Writable or Modifiable might be nice prefixes
little late tho but ye
ah Conclube to the rescue
so I just make methods static and how do I initialize such class in another one?
You manage just fine frosty ;)
you wouldn't intialize the class, you would reference the methods instead
You don't, that's the point of making the methods static
so in that case I can just EntityPDC.setPDC etc.?
like import EntityPDC.setPDC and then just use it?
And by the way, there is the PersistentDataHolder interface which defines the getPersistentDataContainer() method, just in case you didn't know
yeah once you import a static method, you should just be able to use it in the class like you do everything else π
also note it isn't necessary to import a static method either, as just like you are doing or showing
you can just reference it directly, but it does make it easier code wise if you import it though
I know
I just found the fact that defining Namespaced key etc. is just very redundant
since im working a lot on PDCs
so I wanted to make utility class for that
so that I could just return value very fast
so I guess tommorow ill tidy up my plugin more with static methods now that I know how they work
I was referring to your LivingEntity parameter type. You could widen the scope of your function to accept every kind of thing that has a PersistentDataContainer
this is an example of a utility class
Adding a private constructor and marking the class as final is a good convention on top of that
yeah only thing I didn't do with that class lol, but all well
point is, all those methods don't rely on each other, and don't rely on anything else and are self contained
therefore, they are static and can be used anywhere without issues
so I could make damage formula method static without a problem?
and use it in several parts of code like abilities or simple damage by player
and same for FileManager that reads stuff from configs?
sure, but do be careful though with statics. Anything static will never go away and is always loaded
so its something to not over use π
if your damage formula is always going to be used regardless it may be worth making it static as it would improve stuff
yeah as you said
good for pure utility
thats the kind of help I appreciate and am happy to hear
altho I get that not everyone has time or simply wants to explain
Yes, but try to make sure to not reinvent the wheel and think about making stuff static twice, not everything should be a utility class.
You should stick to the native configuration stuff as long as it fits your needs rather than shoving everything in a "manager"
but still that'd be better than just slapping with "you lack fundamentals, go back"
well I think learning about static is something you should learn early on as I consider it something as part of the basics
I know I wouldnt call everything utility for sure
I needed FileManager cuz I use several configs
many people don't learn statics properly and either over use it, or shy away from it because they don't know how to use them properly
so its better you learn about them early as well as how to use them or rather know what the rules are when a static could be used
:3 thx conclube
if an object is never going to go away, IE like your main class, it is acceptable for said object to be static, exception being if you want many objects then you don't want it static
classes, variables, and methods can all be static and are independent of each other
enums are by default static classes just fyi
they can not be anything else
Are stuff like enums or lambda important for plugin making
sure I will show you another handy thing
enums sometimes lambdas a very important
yesnt
its good to know, but its not like there dont exist other solutions
a permissions enum that lets you define * perms for your plugin π
also lets you define dynamic perms too
IE perms you can't know about ahead of time XD
there is always something to look at π
I feel like even tho I went through a course my knowledge is practically a swiss cheese
Bukkit.broadcastMessage(Color.WHITE + player.getName() + Color.GRAY + " >> " + Color.WHITE + message);
Why does the color come up like this?
Shouldnt it be ChatColor?
ye thx
when you use the wrong color imports XD
No
ok hot thx
ChatColor.GRAY + "this is gray" + ChatColor.RED + " this one is red"
wait whats dark gray
Dark_gray
still no idea how to do this without wasting way too many hours on it so if anyone can guide me through it dm me
Same for dark green dark red etc.
need chat components to use hex if I recall
can u explain a tiny more :))\
yes I think so too
at the moment I can not explain more as I have to get ready for work lol
Oh
but the easiest thing to use is MiniMessage for them chat components
Whoops
check out ChatHexCode
or was it HexChatCode or whatever
this is how you do it via nbt in vanilla, it might help
{Count:1,id:"minecraft:trident",tag:{display:{Name:'{"italic":false,"extra":[{"text":""},{"color":"#974DFF","text":"Hex Name"}],"text":""}'}}}
okk thank u
one more thing
does broadcastmessage not support utf8
this
" Β» "
turns into this
is it formatted
wdym
wdym D:
Β§this thing
chat in mc is UTF8
Bukkit.broadcastMessage(ChatColor.WHITE + player.getName() + ChatColor.DARK_GRAY + " Β» " + ChatColor.GRAY + message);
also, java by default is utf8 as well, unless you set it otherwise specifically
use the escape code for this character instead
Yeah ig
\U+00BB
its as if its saving it as text somewhere then fucking it up and loading it again
thats the escape code for that character, guarantees it to show up properly
but yeah try escaping it
wdym ecapin it
use this instead of ChatColor.whatever
thats the UTF-8 code for that character
java knows what UTF-8 characters are, hence can use them directly, and also known as escape code since you have to prepend with a backslash
You want Dark gray right
\U+00BB this is dark gray?
thats just the symbol
thats the double arrow character
you need to add an 8 after that
oh ye i assumed so
Ah wait
what
mb
what are u guys on about π
Bukkit.broadcastMessage(ChatColor.WHITE + player.getName() + ChatColor.DARK_GRAY + " \\U+00BB " + ChatColor.GRAY + message); no?
I am not on about anything, just telling you what the utf8 code is for that character
which guarantees it to show up properly everywhere
when there is issues like you are having, yes
no i mean like
in config files
it translates the symbol to its utf8 code right?
in the code
depends how you its read from the file and is done a slightly differently from config files
ahh ye i get it
so i wouldnt need to code a system like that for config files
it should most likely work if im just reading from there
most times yes
unless someone changed the encoding of the file π
I think snakeyaml enforces utf-8 though if I am not mistaken
should be single slash
also doesn't need quotes either
and yeah no quotes cause otherwise itll treat it as literal text
it should be a single slash, don't remember needing two
one slash
hmmm
can we get the entire line of code
show the whole line
Bukkit.broadcastMessage(ChatColor.GRAY + player.getName() + ChatColor.DARK_GRAY + \U+00BB + ChatColor.GRAY + message);
gl
if you use the bungee chatcolor its not an enum
ye
but wrap the unicode in a string
now you double escape as it's Java
yep
Its hard to advise when you only show snippets. Best to give it all at the start
but i gave the entire broadcast message
what else could u possibly need for that π€
dunno what to tell you blud
sec let me open my ide. Check how to use unicode
@EventHandler
public void onPlayerChat(AsyncPlayerChatEvent e){
String message = e.getMessage();
Player player = e.getPlayer();
message = message.replaceAll("\\s+", " ");
e.setCancelled(true);
Bukkit.broadcastMessage(ChatColor.GRAY + player.getName() + ChatColor.DARK_GRAY + " \\U+00BB " + ChatColor.GRAY + message);
}
would you
try it wihtout the +
and lowercase the u
thats how ive mostly done it whenever it needed to be done elsewhere
never needed to do it in intellij though it was mostly for stuff like server motds
π€
thx
Noo you beat me to it
You too slow and my IDE takes forever to open too
I was busy googling it
Hey, so currently I'm making a custom PathfinderGoal. Basically I'm trying to detect if there is a block in the path of the entity and if so make it jump over the block. Currently it does work/jump over the block but only when the block is set inside the mob (i'm using a giant). I can't seem to come up with an efficient way to get a block in front of the mob without it being inside it's body for this to work. Any help would be appreciated, ill show the two methods i went about it so far below. Also to note im using 1.8.8
Method 1:
Location entityLocation = entity.getBukkitEntity().getLocation();
World world = entityLocation.getWorld();
Vector entityDirection = entityLocation.getDirection();
BlockIterator blockIterator = new BlockIterator(world, entityLocation.toVector(), entityDirection,0.0, 2);
while (blockIterator.hasNext()) {
org.bukkit.block.Block block = blockIterator.next();
System.out.println(block);
if (block.getType() != Material.AIR) {
System.out.println("Block detected");
return true;
} else
// System.out.println("Air detected");
return false; ```
Method 2:
Location entityLocation = entity.getBukkitEntity().getLocation();
World world = entityLocation.getWorld();
org.bukkit.block.Block currentBlock = world.getBlockAt(entityLocation);
BlockFace entityFacing = getEntityFacing(entityLocation.getDirection());
org.bukkit.block.Block blockInFront = currentBlock.getRelative(entityFacing);
if (blockInFront.getType() != Material.AIR) {
System.out.println("block detected");
return true;
} ```
Probably because the giants hitbox is inside the giant
Hm that is true, anyway to so called 'avoid' the hitbox to actually make it work lol
Might have to do some hacky thing and make it levitate at the right time to make it appear right lol. Wont be easy and will have to play around with it
you are only checking 1 block in front of the location
Even with it set to 20 it still only 'jumps' over the block when the block is inside the body
you don;t use the hitbox at all
I reference the hit box because a giants size is smaller according to the server then what the giant appears
yeah, they stopped using giants for a reason π
Lol
The only solution is what i said. You will have to play around how far from the giants real size is to where their feet appear and do some levitating hack lol
It may or may not still look right but that is about the best you can do for this
Yeah it makes sense now that you mentioned the hitbox lol, thanks
how do i make a org.bukkit.Color become a org.bukkit.ChatColor
currently learning how to make a plugin so sorry if this is a basic asf question, but is this how i would format a command that i want to be /verify [PlayerName] [TwitchName] and for all intents and purposes i would just want it to store both TwitchName and PlayerName as a string of some form to a file or something (if thats possible, would also greatly appreciate if someone could point me in the right direction ^-^)
commands:
verify:
description: gets and stores twitch username with player name.
usage: /verify [PlayerName | TwitchName]
aliases: [Verify, verify]
permission: verify
permission-message: you do not have permission to verify?...
Some things you should probably fix with this alone are
- Removing the redundant alias that is the same as the command.
- Making a better permission node. (Usually plugins follow the
<pluginName>.<permission>format. Ex:essentials.banorminecraft.command.ban)
As for how you might want to approach a system like this, you'll want to create a command and use the command arguments to compare what the player entered.
You shouldn't save any data to the config file as that would just be bad practice. However, you can save your information to a file using FileConfiguration.
File file = new File("datafile.yml");
FileConfiguration data = YamlConfiguration.loadConfiguration(file);
data.getString("path.to.your.value");
data.setString("path.you.want.to.edit", "value");
data.save(file);
@clever crescent
God I'm in data structures but I haven't gotten to this yet. I essentially have a node which knows about 6 nodes. I need to navigate through every node within the system. I'm not sure about a great way to do this though.
public record StructureNode(@Nullable StructureNode north, @Nullable StructureNode south, @Nullable StructureNode east,
@Nullable StructureNode west, @Nullable StructureNode up, @Nullable StructureNode down, @NotNull BlockData data) {
each structure node knows about every node around it basically and the data it contains
I wouldn't really want to use recursion here as that would probably kill the call stack
maybe there is a better way to go about this too? idk I'm just trying to find a nice way to build and store structures within memory
I could just run through each direction and add to a call stack, but I feel like that overhead would get insane.
MultiBlock structures are a real pain
tyyyy this helps a ton ^-^ as for the permisson nodes i havent gotten to that just yet, only have it there cause tutorial man said to put it hehe
when you're saying "path.to.your.value" and "path.you.want.to.edit" does this mean that im pulling the value im inputting into the command? and is path that i want to edit in reference to location in the file or like whether im appending to the file?
currently how im formatiing it
{PlayerName} {TwitchName}
{PlayerName} {TwitchName}
{PlayerName} {TwitchName}
{PlayerName} {TwitchName}
{PlayerName} {TwitchName}
{PlayerName} {TwitchName}
@river oracle
Maybe treat the nodes using a vector as direction
Also idk how u won't use recursion for something like that
You could maybe make a queue and while loop ig
YAML files work using sections and subsections. In order to access a subsection using the Spigot API, you use the . to specify that you have a subsection.
section:
subsection: test
subsection2: 15.9
sub-subsection: 8
If you wanted to get the value of subsection2, you'd use FileConfiguration#getDouble("section.subsection2").
If you wanted to set the value of sub-subsection, you'd use FileConfiguration#set("section.subsection2.sub-subsection", 9)
Oop, made a mistake. You can't actually have a value on the direct parent of a subsection.
subsection2 is formatted incorrectly, but the principle is the same
section:
subsection: test
subsection2:
sub-subsection: 8
It would have to look like that
Might jus t approach it from a different way multiblocks got me going crazy
And of course, the names of the sections can be whatever you want. Just be aware that some names are reserved for the yaml parser and might not correlate to the value you want if you're not careful.
so instead i would do?
but does this imply that im not able to append a new section to the YML file?
like would i be better off storing 2 raw strings in a TXT or like a different file type?
player1:
PlayerName: ingameusername
TwitchName: twitchusername
cause the end goal is to make players when they join do /verify [minecraftname] [twitchname]
and then store that and compare later
You can append however many sections you want to a yml file. #set() should automatically create the section if it doesn't exist.
If it doesn't for whatever reason, you can use FileConfiguration#createSection("section.path")
Also, something you may want to consider is using the player's UUID instead of their name. Since player names can be changed at any time, your data may become outdated and behave in a way that you don't want. It would also cut down on the number of lines you need to write to disk.
03687ca0-30cf-4c3c-8c1d-3b2dd75c3ff0: "MyTwitchName"
That's my UUID btw
oooo i like that idea
so instead of creating a section that is the players name with twitch name as the value, i just pull their player ID and set that inplace of username instead.
i think where im getting lost is how i translate the data i input into the command into a string that i pass to the file
FileConfiguration#set() is a flexible method. It has tons of overloaded methods so you can pass in whatever data type you need.
If you wanted to store data like the example above, you'd just call it like this,
datafile.set(player.getUniqueId().toString(), "TheirTwitchName");
If you wanted to put all that data into a subsection, you could format your file like this.
data:
03687ca0-30cf-4c3c-8c1d-3b2dd75c3ff0: "MyTwitchName"
Then you just need to prepend the section name to the set method. datafile.set("data." + player.getUniqueId().toString(), "TheirTwitchName");
How you store your data is up to you, but since these files are easily editable, I like to keep them as easy to understand for the end user as possible while keeping it concise.
Thanks, i just found a new conversation prompt that i didnt know existed
Went searching in the api in relation to what you were stating and inadvertently found a new prompt lmao
this makes A TON more sense than it initially did haha, i had a fundamental misunderstanding of what you meant by the #set() so i was looking around for a different thing i hadnt used haha. tysm haha its super weird wrapping my head around things that are similar to base java stuff but slightly different haha
i still have to figure out how to pass the data the player gives the command but that should theoretically be a google search away
declaration: package: org.bukkit.conversations, class: FixedSetPrompt
In case you are curious
Think this might be useful when i update server tutorial
I still need to learn how to use those. lol
My plugin uses the conversation api
I dont so anything too fancy with it. But what is nice about it is you can use it to kind of simulate chat
In case you want to get fancy with entities and channels
I make use of the channel bit so that normal chat doesnt interfere and when they are done they still retain normal chat history
Maybe this weekend i will update it
Going to implement display entities into it
Which also means new api as well 
Ohh, I think I see how that works now. Just a bit of chaining.
You can chain them but dont have to. And you can loop back around too
Just have to call the relevant prompt
Which i do implement in a couple of places where they dont give a correct response
Or if the response given doesnt parse properly
Ahh yep. I see that too.
Also i specify a keyword as well so they can exit out as well
That propagates all the way down right? So it's only defined once?
Yep
Nice
And the context can hold arbitrary amounts of data too
Kind of like a cache for the duration of the conversation
You set your own key and data and it also has some predefined keys if i remember right. Been a while since i messed with it lol
Its sad though its one of the most under used api as well given how old it is
Existed since 1.6-1.7
I thought the Conversation API was added in 1.12 or 1.14 lol. (Yet another reason for me to complain about not having @since tags) reeeeeeeeeeeeeeeeee
Lmao
Just have to remember is all
I think this might be overwhelming the new person
Maybe. I kinda dropped a lot of info. Could have gone further into technical details though. >:)
I work with config files far too often.
Ironically that is what i use the conversation api for
im definitely having some form of fundamental misunderstanding lol nothing ends up in the .yml file after I type the command, dispite me passing the args into the value at data.set("data." + player.getUniqueId().toString(), TwitchName); and i have a red underline on .save in data.save(file);
public class Verify implements CommandExecutor
{
String TwitchName;
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String [] args)
{
TwitchName = args[0];
Bukkit.getLogger().info(TwitchName);
if(!(sender instanceof Player))
{
sender.sendMessage("Only players can send this command");
return true;
}
Player player = (Player) sender;
File file = new File("PlayerStreamData.yml");
FileConfiguration data = YamlConfiguration.loadConfiguration(file);
data.set("data." + player.getUniqueId().toString(), TwitchName);
data.save(file);
return true;
}
}
//this is how i initialize the file on server startup in the "main" class
try {
File PlayerStreamlist = new File("PlayerStreamData.yml");
if(PlayerStreamlist.createNewFile()) {
Bukkit.getLogger().info("Player Whitelist File Created:" + PlayerStreamlist.getName());
} else {
Bukkit.getLogger().info("file " + PlayerStreamlist.getName() + " already exists");
}
} catch (IOException e) {
Bukkit.getLogger().info("an error has ocurred while creating or checking for player stream list file");
e.printStackTrace();
}
To make it easier for a server admin or mod to edit the tutorial stuff
The reason for the red line is because #save() throws an IOException. You can just surround it in a try catch.
Make sure to implement a nice error message too
Its good practice to just not only catch the exception but actually do something lol
Or you can just mystify your users or yourself with some stack traces like most do
You may also need to specify the parent directory for the file. Which can be done with JavaPlugin#getDataFolder()
File file = new File(plugin.getDataFolder(), "PlayerStreamData.yml");
You'll also need to make sure the file exists before you can save data to it.
Maybe should have pinged them? Lol
tf
I clicked their post as the reply. lmao
I got the discord bug
After all this time
Ah
the making sure it exists is what the try catch in main is for, unless that doesnt do what i think it does lol
also il ltry the parent directory rq
Anytime you mess with io it needs to be surrounded with try catch unless your lazy and state your method throws io
But you will still at some point at least catch it one time
Oh, I missed that lol. Everything should work as long as the file exists before you try and save data to it.
Saving data still throws io exception
Because even though file exists there can be issues with writing
Cause of perms, no more room etc
true true
try {
data.save(file);
} catch(IOException e) {
Bukkit.getLogger().info("oops no save hehe c:");
e.printStackTrace();
}
that would do the trick i assume?
Yep
Yeah that works
At least with the nice message makes it easy where this error comes from lol
How do i start making plugins
And with that, back to doing my tire related duties. Gotta figure out what is to be done with my door since someone broke it
Duct tape is a great temporary solution. Used it to fix my bumper that someone ran into. They ended up breaking the plastic clips that hold it in place.
success! tysm :D
Althought that reminds me. I still need to get it properly fixed. lmfao
Door is bent to hell on one side so when it closes you cant lock it. The door has a place holder for the lock we use so that it makes it nearly impossible to break the lock. We have round locks
Doubt duct tape will fix this lol
Either someone on the previous shift did this and said nothing or someone ran into it again
Hmmm
Not really a big deal if someone broke it, but people are dumb in speaking up lol
Gonna break out the torch and mallet? bang it back into roughly the original shape?
Or just get enough for the clearance. lol
Probably wont use the torch and most likely will be our building maintenance guy in the morning. Its what they did last time when someone hit it with a box truck
One day i will get a new door
Most likely going to be this and i will have to deal with it after that lol
As long as it can open and close and lock that is all they care about
Yea, that's typically what happens. At least what I'm used to seeing.
My floor basically turned to powder in one spot
It was filled in with fiber glass lol
Not that a fork lift needs to drive in there or anything XD
I use a squeeze lift and it has to go inside of there. Fortunately that fiber glass has held up thus far
Hole was like offset from the center to the left so i drive over that spot a lot
Floor is like 3/4 wood except at the very ends its metal
Ah, that makes sense now. I was assuming the floor was concrete and they were patching it with fiberglass.
Lol. Its a connex box
Soo why would EntitySpawnEvent be casted when an entity dies? I don't have any events for deaths currently, but everytime I kill one of them a random monster spawns ( my custom ones ). I'm so confused.
mob cap?
shouldnt be hitting it
Mc wants there to be x monsters
And mobs
When one dies
One needs to be replaced
πͺπ»
Simplified
Cut off the head of one and two more takes it place
really thats what it is?
but why? im replacing a mob that has spawned it should've taken its place. therefor wouldnt it spawn somewhere else instead right on where it died?
cause it would really fuck with someone if a boss death summons another boss. people would be pissed.
cause like well they arent easy lmao
If it's th same mob spawning then you have some plugin messing stuff up
Print exactly the events, maybe with an exception to get a stack trace
wym print exactly the events?
spawn and death ig
Print the entity involved in both
[02:29:46 INFO]: CraftExperienceOrb
[02:29:46 INFO]: CraftVex
[02:29:46 INFO]: CraftExperienceOrb
[02:29:46 INFO]: CraftExperienceOrb
[02:29:46 INFO]: Named entity EntityEnderman[' Slack'/258, uuid='d727dca0-24d8-42de-811e-f9d5b584ab03', l='ServerLevel[world]', x=-61.45, y=63.00, z=370.82, cpos=[-4, 23], tl=12, v=true] died: Slack was slain by ToastARG using [The Furnace]
[02:29:48 INFO]: CraftZombie
[02:29:48 INFO]: CraftEnderman
[02:29:48 INFO]: CraftEnderman
[02:29:48 INFO]: CraftVex
[02:29:48 INFO]: CraftEnderman
[02:29:48 INFO]: Named entity EntityEnderman[' Slack'/269, uuid='5620a417-4a61-45bd-bfb4-5416fee0853c', l='ServerLevel[world]', x=-61.03, y=63.00, z=369.43, cpos=[-4, 23], tl=11, v=true] died: Slack was slain by ToastARG using [The Furnace]
[02:29:49 INFO]: CraftSkeleton
[02:29:49 INFO]: CraftCreeper
[02:29:49 INFO]: CraftEnderman
[02:29:49 INFO]: CraftItem
this was all during the spawn of the enderman, and the death. i killed him and another spawned. i killed a zombie a slack spawned, once i killed that slack again, another spawned, then it stopped.
Do you have some kind of task for spawning?
All I am doing is checking for every spawn event and there's a chance for each one of my monsters to take that place. highest chance is 11% rn lowest is 4%.
Alright. How often does it check and did you consider if certain limits are hit?
is there any method to check if the player is standing on ground or not, since isOnGround() is deprecated
I will give an example
What does it link to?
nothing
it checks for every entity spawn, and if one of the spawn chances hits it continues the rest if not it just ignores it. idk of any limits
it just says it can be spoofed by the client and so is inaccurate
If the limit is 89% full. That means your 11% guarantees a spawn and the minimum still yields 93% odds
getting the player location and checking the block under it also isnt always accurate because it doesnt account for the player sneaking off the edge of a block so i was thinking using the players bounding box and checking the 4 bottom corners of it and seeing if theres a block under that
but i reckon that'll fail for blocks that arent complete like fences
Hope that made sense lol
private static void summonMonster(EntitySpawnEvent event, Monster monster, Double spawnChance, Integer radius){
Random random = new Random();
if (!(random.nextDouble() <= spawnChance)) return;
event.setCancelled(true);
Location spawnLocation = event.getLocation();
Player nearestPlayer = Players.findNearestPlayer(spawnLocation, radius);
if (nearestPlayer != null) {
MonsterType monsterType = CalculateAttribute.DetermineType(LevelManager.getLevel(nearestPlayer));
Monster.SummonMonster(monster, spawnLocation, monsterType, nearestPlayer);
}
}
this is how im doing it, idk if i took yours another way but it didnt sound like what i was doing.
You are forgetting to factor the server mob limits as a whole and per chunk
So here is another example
Yeah but it's being replaced no? im cancelling the orignal and using my own.
it should just stay the same.
Depends how many times its called i guess lol
could it be that you recall the event with your summon
its only when it spawns tho. death shouldnt trigger it.
either it spawns naturally or forced by a command, they both do the same thing, forced or natural spawn by taking somethings place.
The spawn rate for trying to spawn a mob must be fast enough that it appears mob spawn is guaranteed. You should add a delay to counter this. But probably should print a debug message for every spawn along with time
how would i delay it?
You would just create a delayed task or better yet just create a que management system to handle your custom spawns and be independent of spawning all together and dont have to worry how many you cancel except continue intercepting the command ones
Should solve your issue and basically give you all the control you want
I wouldn't even know how to create the que system, and I just still don't understand why it doesn't work properly. any other time if done something like this i didnt have this issue. But I changed how I create, and manage them, I didn't really change how they were spawned.
all i did was make some things easier down the road
Well as i said it could be the spawn rate. If the mob limit is high and amount of mobs total low and there is plenty of areas to spawn the server can easily spawn 20 mobs every few ticks until about half or so full towards the limit
could i check if i've reached the mob limit, and remove something else instead to make room?
Lets say 20 mobs try to spawn each tick for 20 ticks. How often will 11% be hit? Lol
Probably
These limits are in spigot.yml
if i increased those would that fix it? cause that also seems like a good option.
You would want to decrease
i thought we had to make room for it to spawn? if i lowered it woouldnt that make it worse?
There is spawn rates, overall server entity limits and per chunk limits
ohhh
Make a copy of spigot.yml so you have defaults handy. Messing with these can take time lol
yeah and damn i've actually never opened this file before. there's actually a lot of shit in here.
Yeah
entity-activation-range:
animals: 32
monsters: 32
raiders: 48
misc: 16
water: 16
villagers: 32
flying-monsters: 32
What are these?
How far you can be for those types of entities to move or do things
Those are in blocks
ahhh okay, so if i were to have custom follow ranges, this would be necessary.
So animals will move around if your 32 blocks or closer but once farther they stop
Or freeze to be more accurate
Sometimes. Depends how you implement the following lol
true..
If you use goals most likely. But if you handle the movement manually most likely not
I'm not seeing what i need to change for those rate limit things.
Check bukkit.yml then
yep spawn-limits is here
spawn-limits:
monsters: 70
animals: 10
water-animals: 5
water-ambient: 20
water-underground-creature: 5
axolotls: 5
ambient: 15
chunk-gc:
period-in-ticks: 600
ticks-per:
animal-spawns: 400
monster-spawns: 1
water-spawns: 1
water-ambient-spawns: 1
water-underground-creature-spawns: 1
axolotl-spawns: 1
ambient-spawns: 1
autosave: 6000
Which of these do i modify?
just the spawn limits or also the ticks-per?
Ticks per is how many globally will try to spawn
While 400 may seem high for animals have to remember not all spawns will succeed
do we know aprox how many fail?
Spawn limits, is how many globally and i think the chunks one resides in spigot.yml
Each entity type has their own conditions that lets it succeed
that makes sense
So for example spiders. A spider will try to spawn if the light level is low enough and there is at least a 1 block space for it. If it comes from a spawner the limit is 16 blocks all around the spawner
Okay, so how would i adjust these to fix my problem? We'd want it lower?
Well this is where you get to have fun lol
fuck with it till it works lmao
that'll be tommorows task then. its 3;30am here. At least i know what the problem is now.
I appreciate the help!
Or you can just implement your own system and not mess with this up to you lol
hey how i can find for read craftBukkit code
craftSpigot too
tried to find it but couldn't find it
?stash
thf
what is CraftSpigot
Is it okay if I have static methods and event listeners that are registered in a class?
What do the static methods do
Generally or in my particular case?
Your use case
Olivo is a newbie, please explain it to him
a very smart newbie tho
One for calculating damage and one for mob health bar management
I doubt that every class that'd use any of those would need to have separate instance
But im curious if I can mix it like that
Static methods and event listeners in one class
Its in the buildtools directory under work
For the nms stuff and then the cb and spigot is in their respective directories
Can import them into your ide if you want
Stash only gives you the api and git patches
Any method or object that manages something generally shouldnt be static
Singleton is one thing, but static it typically shouldnt. Reason being if for some reason you need to clear it out to refresh you wont be able to
If its static
So I keep it as is?
Yep wont hurt anything. Also later down the road you might want to do some abstraction with it or something else. If it's static this makes it harder to do and you end up changing it back anyways
Is it any not super okay if I make instances of class with listeners despite not using them in those instances?
So this is not the whole project?
Rewrite your sentence so we can understand it
Would there be an easy way to find an items display name (when it's not set) other than getting its type and then putting it to lower case, and capitalizing each letter at start of a new word? So NETHERITE_SWORD becomes Netherite Sword?
Or is it just something you have to sit and create a translation for each item?
I found out that if you do meta.getDisplayName() from an ItemMeta, you won't get any unless the item has been set a name by an anvil or the .setDisplayName function
1.20
Guess not
Well that sucks. I guess I could cheese it by setting a displayName when it's being crafted?
It's just weird that it doesnt register the display name automatically since there clearly is one there ... π¦
Nevermind, it's way cleaner to just remove underscores, lowercase and uppercase each new word and I guess that's just how Mojang made it as well
free Microsoft Java lessons
Displaynames are localized
A danish user will see βStenβ for Stone etc egΓΈtc
Etc*
well, you can't, because items are different for users with different locale
tho you probably can find a library which has a method for returning item base name for each locale like LanguageUtils
It does
What do you not understand
Your sentence
what
What exactly isnt understandable
wdym instantiate a listener class and don't use it
you mean like not register it?
well, i already mentioned it, but it's too old for him ig
it returns a pair en_us ig
in lowercase
wiki states it's in lower
the locale key at least
the display might be like en_US
why do you need that tho
maybe you can do smth else
I mean for cases like displaying your current held item to chat you can use ChatComponents and Locale settings
Nah ill just remove underscore etc etc.
Its way easier. All I'm doing is making a death message hehe
Just wanted to include the weapon name if any item was used
Next step is to learn how to link the item in the chat so it looks even cooler
well, only display the item name if it has one
otherwise just say "Player died from some shit"
Yea ik
"&aPlayer was killed by &csus"
Sir thats illegal
I have a class, it has listeners and some normal methods, is it okay if I register listeners with one instance and use other instance to just use those methods
Or should I split them
learn OOP and just separate stuff
2 instances of something is kinda cringe in general(except stuff which is mass-produced(like all zombies in the world) or has a hard but big limit(all server players))
So if I want to use those methods I make one instance in main class and pass it to other classes?
Wouldnt it be easier to just make it static?
i need to unfroze biomebase registry to create custom biomes, how can i get registry?
here is my code now:
RegistryMaterials<BiomeBase> materials = ((RegistryMaterials<BiomeBase>) dedicatedServer.aU());```
i cant understand what i need to write after aU()
like which method
in 1.19.2 it was java dedicatedServer.aX().b(IRegistry.aR)
?mappings
Compare different mappings with this website: https://mappings.cephx.dev
ty
That gets the language that is set
By the client depending which locale it is otherwise if its the wrong one it gets the locale of the server instead lol
@EventHandler
public void onBlockDropItem(BlockDropItemEvent e){
if(e.getBlock().getType() != Material.LIGHT_BLUE_WOOL) return;
e.setCancelled(true);
e.getItems().remove(0);
if(e.getPlayer().getInventory().getItemInMainHand().getType() == Material.SHEARS) return;
HypixelPlayer playerAccount = HypixelSkillCore.getInstance().getPlayer(e.getPlayer().getUniqueId());
playerAccount.setMithrilPower(playerAccount.getMithrilPower() + playerAccount.getMithrilFortune());
if(playerAccount.getMithrilPower() > playerAccount.getMaxMithrilPower()){
playerAccount.setMithrilPower(playerAccount.getMaxMithrilPower());
}
}```
why is this still dropping the light blue wool
@spare hazel did you set api-version to at least 1.13 in plugin.yml?
okay
my guess is the getBLock() is already set to air
dude we're so smart
theres no getBlockState
declaration: package: org.bukkit.event.block, class: BlockDropItemEvent
oh nvm
declaration: package: org.bukkit.event.block, class: BlockDropItemEvent
1.17 has it too
call it on the event, not on the block
if(event.getBlockState().getType() == Material.LIGHT_BLUE_WOOL) or sth like that
why do some plugins have a folder with a bunch of modules?
because they use NMS
what his mean
NMS is version specific code
it uses minecraft internals
not just spigot api
and those change each version
This helps separate classes that are the same but for different mc versions
https://blog.jeff-media.com/maven-multi-module-setup-for-supporting-different-nms-versions/ here's a guide on how to do that. but you should avoid using NMS unless it's absolutely necessary
Hi there! Today Iβm going to explain how to setup a multi-module project using maven to support different NMS versions. Important notes about this tutorial: Every step will have detailled screenshots using IntelliJ. I explicitly chose not to include everything as copy/pastable source code, but normal screenshots (you can click on them to show th...
support for different versions?
NMS is not needed in 99% of cases on modern spigot versions
it used to be required a lot in old versions, e.g. to send action bar messages in 1.8
but in 1.20 there is very little reason to use it
using NMS means your plugin will most likely break on major updates
well yeah for simple stuff it aint needed esp if you dont mind using protocol lib
add debug statements
before every return, print out why it returns
oh i know why
why?
Did u register it
does this mean that all these modules are different versions of the plugin?
@EventHandler
public void onBlockDropItem(BlockDropItemEvent e){
if(e.getBlock().getType() != Material.LIGHT_BLUE_WOOL && e.getBlockState().getBlock().getType() != Material.LIGHT_BLUE_WOOL) return;
e.setCancelled(true);
e.getItems().clear();
e.getBlock().getDrops().clear();
e.getBlockState().getBlock().getDrops().clear();
e.getPlayer().sendMessage(e.getBlock().getType().toString());
e.getPlayer().sendMessage(e.getBlockState().getType().toString());
if(e.getPlayer().getInventory().getItemInMainHand().getType() == Material.SHEARS) return;
HypixelPlayer playerAccount = HypixelSkillCore.getInstance().getPlayer(e.getPlayer().getUniqueId());
playerAccount.setMithrilPower(playerAccount.getMithrilPower() + playerAccount.getMithrilFortune());
if(playerAccount.getMithrilPower() > playerAccount.getMaxMithrilPower()){
playerAccount.setMithrilPower(playerAccount.getMaxMithrilPower());
}
}```
still no result
Whats nms command
you still check e.getBlock().getType()
Only some part of it
@spare hazel smh
Use || if u want to keep the starting thing
getBlock().getType() will almost always be AIR
Learn to use the API before delving into mc internals.
nms command?
Im asking what was the ? Command for nms post
?nms
