#help-development
1 messages · Page 2105 of 1
still doesn't show up
hm it shows up after rejoining
so yeah the group thingy works fine but discoverRecipe is still behaving weird unless you rejoin
Did you reload the server when loading that plugin?
wdym? after calling "discoverRecipe" it doesn't show up, but when you rejoin, it does show up
seems like "discoverRecipe" only tells the server "player got the recipe" but doesn't inform the client about it
Did you run /reload at any point during your testing?
no
Odd. I've had a different experience when it comes to recipes. They just kinda show up when I add them.
is there a method to get all permissions a user has when they join
instead of checking hasPermission
get all perms so I can drop them in my db
getEffectivePermissions()
ty
that returns a Set<PermissionAttachmentInfo>
depends on the vector
any vector
you're doing something wrong
what do you set the velocity to?
I bet setting it to 1,1,1 will work fine
you're probably setting it to some way too large thing
sending it straight up with a magnitude of 1 - 2
it works 100% fine
@Override
public void onEnable() {
getCommand("test").setExecutor(new CommandExecutor() {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
commandSender.sendMessage("Setting velocity to 0,1,0");
((Player)commandSender).setVelocity(new Vector(0,1,0));
return true;
}
});
}
a spawned entity tho
I spawn wolf, then set velocity to (0, 1, 0) immediately
it goes up but then it immediately spikes down
for some reason
I think you need to apply velocity on the next tick if you are spawning mobs into existence.
nope
you can do it directly
and it works fine
@Override
public void onEnable() {
getCommand("test").setExecutor(new CommandExecutor() {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
commandSender.sendMessage("Setting velocity to 1,1,1");
Entity entity = ((Player)commandSender).getWorld().spawnEntity(((Player)commandSender).getLocation(), EntityType.ARMOR_STAND);
entity.setVelocity(new Vector(1,1,1));
return true;
}
});
}
?paste your code pls
my code just worked the first time through perfectly and i dont know wether to be scared, concerned, or just accept it
it's probably bugged and you just don't know it
I always go "yay it isn't throwing an exception" and then I realize it isn't even being called anymore
Well like, im making an annotation that auto registers a command, and the command runs suprisingly
its gonna break sooner or later i feel it
it definatly can have 4 annotations, could add them as optionals
suprisingly the code for the reflection access to this was stupidly simple
havented tested dependency injection for JavaPlugin's though
im sure thats fucked
Edit: broken as shit gg
where can i look for information about permissions?
What type of information specifically?
permissions are basically simply a Map<String,Boolean>
well not exactly but pretty much
what does that have to do with permissions?
as a starting point, see i used a word. it turned out to be the wrong word. oops
what kind of settings do you want to store per player?
also do you need those settings to be accessible even when the player is not online?
nope. basically just a boolean value as a well
I'd just use the player's PersistentDataContainer
definitely the easiest way if you only need to store one boolean per player
or metadata if its per-session
yeah, do you need it to be persistent about rejoins / server restarts, or not?
ideally it should stay forever
then use the player's PDC
ill be toggling the value via a command
public boolean getPlayerSetting(Player player) {
return player.getPersistentDataContainer().getOrDefault(settingsKey, PersistentDataType.BYTE, (byte) 0) == (byte) 1;
}
public void setPlayerSetting(Player player, boolean enabled) {
player.getPersistentDataContainer().set(settingsKey, PersistentDataType.BYTE, enabled ? (byte) 1 : (byte) 0);
}
we're using bytes here because spigot doesn't have a boolean type builtin
ah. i didn't realize that you could cast directly to byte. that is extremely helpful
oh also, the settingsKey is a NamespacedKey,where "this" is the main instance of your plugin:
private final NamespacedKey settingsKey = new NamespacedKey(this, "name-of-the-setting");
i used that for recipes, so im good on that. but thanks anyways for this!
np
checking PersistentDataContainer#has() should be enough to ensure that i dont get null when using PersistentDataContainer#get() right?
What event will trigger when a item is clicked by an item inside the inventory. I have a feeling it is InventoryInteractEvent but im unsure
inventoryclickevent
👍
yes, but as I sent above, you can also just use getOrDefault
oh. derp
getOrDefault will return the given default value (in my case above, "(byte) 0") if it's not set
i always do things the hard way. 🤦♂️
i feel like i should ensure every player have the key when they join though so that doesn't become a problem.. do you see anything wrong with that?
not really, but I don't think it's necessary
just put your check whether they have it enabled into one method that always uses getOrDefault
but ofc you can also just save it to them onJoin, doesn't really matter
well
wait
it does matter
right. ok, i guess it makes it less messy
imagine the following situation:
- admins can decide whether the default value is "true" or "false" for new players
- a player joins. default is currently set to "false"
- "false" gets saved to that player
- admin changes default value to "true"
- the player will still have false now
If you use getOrDefault instead, the new "default" value will apply to everyone who never changed the value themselves.
If you set the value on join, the new "default" value will only apply to people who had never joined before
so it depends on what behaviour you'd rather like
well it seems that if i use getOrDefault there is more of a possibility of using a config file to globally specify the default value
I'm loving it
which is good
and config files are good for admins as they are common amongst plugins already
if you plan to add further config options later on, i'd probably directly store a yaml file in the PDC, or create a custom PDC data type for the player settings btw
yeah, ok. getOrDefault has a lot going for it. i think thats what i should go with
yeah that's what I'd use too
but yeah I tend to simply create my own PDC type so I can easily expand it later on: https://paste.md-5.net/atinipedub.java
lol. untintended consequence happened. but thats unrelated
but the fact that it happened means that my PDC value works
programmer error. obviously
btw maybe my tiny lib might be useful for you: https://www.spigotmc.org/threads/more-persistent-data-types-collections-maps-and-arrays-for-pdc.520677/
it adds stuff like DataType.BOOLEAN but also lets you use Maps, Collections and Arrays for EVERY data type, etc bla bla
how do i get the right sound for the given material
something like
Material.AIR.getSound()
declaration: package: org.bukkit.block.data, interface: BlockData
e.g. Bukkit.createBlockData(Material.DIRT).getSoundGroup()
thanks
then you can do getPlaceSound(), getStepSound() etc
the chin of this dude is way too large lol
also why is his neck like half a meter
not my type
he is chad
some things are "kinda wrong":
first: give your variables proper name. "player" instead of "p"
second: do not blindly cast "cs" (which should be called "commandSender" or "sender" instead) to Player without checking if it actually is a player
it is shorter but you have tab-complete in your IDE
also imagine it's not a player, but an event that you call "e"
now 100 lines later, you wonder "is e an entity or an event or an exception"
but yeah you should use proper names although that's just a tiny thing I wnated to mention
third: you shouldn't check the command's name, but only register commandexecutors to the right command in the first place
you should actually never need to check "cmd.getName()"
fourth: this kinda code is pretty much duplicated:
if(p.isFlying() || p.getAllowFlight()){
p.setFlying(false);
p.setAllowFlight(false);
p.sendMessage("§6Player flight is now disabled!");
return true;
} else {
p.setAllowFlight(true);
p.setFlying(true);
p.setFlySpeed(speed);
p.sendMessage("§6Player flight is now enabled!");
return true;
}
I'd do it like this: (1 min pls)
yeah that's uh
how would i go about making a config.yml for my tab plugin
i have the main config set up
boolean isFlying = !player.isFlying();
player.setFlying(isFlying);
player.setAllowFlight(isFlying);
player.sendMessage(isFlying ? "You are now flying" : "You are no longer flying");
return true;
just not sure how id get that to be as many lines as the user wants
and fifth: You should not hardcode the § section sign for color codes, it might no longer work in future versions. Instead rather use ChatColor.translateAlternateColorCodes
boolean flying = player.isFlying() || player.getAllowFlight();
player.setFlying(!flying);
player.setAllowFlight(!flying);
player.sendMessage("§6Player flight is now " + (flying ? "dis" : "en") + "abled!");
im pretty sure its the byte, and that character is just represented to that byte
well that's also pretty dirty because you probably don't wanna hardcode the actual message but make it configurable 😛
currently, yes, but that might change in the future
utf 😔
So when using PDC to store custom enchant data(name), do I use a PersistentDataType or String to hold the enchant and do this for each enchant I add?
the "§" is implementation specific and so one shouldn't just assume it'll never change imho
I just mentioned it because they asked for improvement ideas
anyone
I'd probably create my own enum for enchantments and then map them to a string / Enum.valueOf or sth
?configs
See this wiki page on how to use custom configuration files: https://www.spigotmc.org/wiki/config-files/
So when I do Enum.valueOf I have the enum and then the string will be the name or the enchant?
this'd be my suggestion:
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("This command is only available for players.");
return true;
}
Player player = (Player) sender;
float speed = 0.03f;
// Not needed, just set the permission in plugin.yml
/*if (!player.hasPermission("frostycore.pfly")) {
player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4You do not have permission to use this command"));
return true;
}*/
final boolean isFlying = player.isFlying() || player.getAllowFlight();
player.setFlying(isFlying);
player.setAllowFlight(isFlying);
if(isFlying) player.setFlySpeed(speed);
player.sendMessage(ChatColor.translateAlternateColorCodes('&', isFlying ? "&aYou are now flying." : "&cYou are no longer flying."));
return true;
}
ye i know that but what in it
I think I roughly understand
btw you can basically ignore the whole "doesn't have permission" thing if you simply register the permission in your plugin.yml
i want it to be like
header:
- 'blah blah'
- 'blah blah'
- 'whatever you want'
footer:
- 'something'
- 'hahhahah'
that wiki
but not with a set amount of lines
I don't understand what your question is
like a tab config
literally just read the wiki
saveDefaultConfig();
List<String> header = getConfig().getStringList("header");
List<String> footer = getConfig().getStringList("footer");
but what do you mean with "a set amount of lines"?
how can i spawn the block break particles
this only spawns at the given location
not like the natural break
generate some random
wdym
like add some random to the location
the spawnParticle methods takes some floats or doubles for random offsets
?jd
?jd-s
this is what I meant: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/World.html#spawnParticle(org.bukkit.Particle,double,double,double,int,double,double,double,double,T)
declaration: package: org.bukkit, interface: World
Just making sure is this roughly what I should do. for each enchant just add it to this and then when setting the enchant on the item I add the enchant name listed into the PDC. So when I get the string from the PDC I check it against the enum to see if it is a enchant?
basically yeah, but normally enums have NAMES_LIKE_THIS
e.g. UNBREAKING, CURSE_OF_BINDING etc
I'd probably save an EnumMap<EnchantEnum,Integer> into the item's PDC
so e.g. you could store stuff like
UNBREAKING -> level 3
CURSE_OF_BINDING -> level 1
in the item meta
why are you creating a whole separate enum? the api already has a pseudo-enum for enchants
for my own custom ones
it's not meant to be extended, it requires reflection, and it causes trouble when combining enchantments
oh I didnt realize custom enchants were involved, I just saw UNBREAKING and CURSE_OF_BINDING and was like, those are vanilla
I'd use a custom Enum for my enchantments and use my PDC lib to store them as a EnumMap on the itemmeta: https://www.spigotmc.org/threads/more-persistent-data-types-collections-maps-and-arrays-for-pdc.520677/
E.g.
EnumMap<MyCustomEnchantment,Integer> enchants = pdc.get(someKey, DataType.asEnumMap(MyCustomEnchantment.class, DataType.INTEGER));
yeah it was just an example to show how you normally name enums
bukkit does that automatically
commands:
test:
description: Some command
permission: some.permission.name
in plugin.yml
now everyone needs to be OP or have some.permission.name to use /test
it knows that automatically since you use getCommand("test") to set the executor
and the permission is attached to the command using plugin.yml
i still don't know why you're checking the command's name
the command name will always be "pfly"
also your code style is weird
sometimes you do
if(statement) { // bracket on same line
and oher times you do
if(statement)
{ // bracket on next line
you're missing the space from the if
i never put spaces there
disgusting creature
pretty sure its required in google codestyle
and what google says, you do!
I don't work for gnoogle 😮
i'm fine with any style as long as the brackets are on the same line
tbh I don't think it's worth to even think a second about this kind of stuff
just let intellij format the code before you push and everyone is happy
Yeah well I think it’s all that matters
based
So we’re at an impasse
let's fight about important stuff
like why are people comparing the command name in their command executors
does this work, do not freaking try it and see me
public static final String PLUGIN_VERSION = "${project.version}";
maven
no
got it
but you can make it work
how
Try it and see
it's something called generated-classes or so
one sec I have it in one project
put the classes into src/main/java-templates
then
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
<version>1.0-alpha-3</version> <!-- Be sure to use the last version. Check on the website's plugin -->
<executions>
<execution>
<id>filter-src</id>
<goals>
<goal>filter-sources</goal>
</goals>
</execution>
</executions>
</plugin>
too much work im good
but it has some weird side effects so I stopped using it
easier way is to use a properties file to get that kinda stuff
since properties are filtered by default anyways
e.g. bukkit does it like that for Bukkit.getBukkitVersion()
public static String getBukkitVersion() {
String result = "Unknown-Version";
InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties");
Properties properties = new Properties();
if (stream != null) {
try {
properties.load(stream);
result = properties.getProperty("version");
} catch (IOException var4) {
Logger.getLogger(Versioning.class.getName()).log(Level.SEVERE, "Could not get Bukkit version!", var4);
}
}
return result;
}
this is from Bukkit's "Versioning" class
i really hope thats cached
(no idea why it reads the file EVERYTIME - it should rather be cached on startup)
BRUH
One last thing and then ill stop bothering you. How do you set? I've got as far as the photo underneath but I cant seem to find a way of putting the EnumMap into it
so if you don't access Versioning yourself, it's fine
are you using my library I linked? Because if not, you'll have a VERY BAD TIME trying to save a map to a PDC
yeah I am
okay then you can do something like this: (one second, let me write sth down quickly)
false
i know of a method on how to
@sand vector
yeah sure, writing something yourself lol
took me about a whole day to get collections, maps and arrays neatly working with EVERY PDC type
So like this (Dw about naming I'll change it in a bit)
example for a EnumMap<Material,Integer>:
@Test
void test() {
EnumMap<Material,Integer> map = new EnumMap<>(Material.class);
map.put(Material.DIRT, 1);
map.put(Material.STONE, 2);
// Save the map
pdc.set(key, DataType.asEnumMap(Material.class, DataType.INTEGER),map);
// Load the map again
EnumMap<Material,Integer> savedMap = pdc.get(key, DataType.asEnumMap(Material.class, DataType.INTEGER));
}
too lazy to write the method
can you explain your idea though?
I'd be interested in how you'd do it
Thanks! That has saved a bit of my time working out how to do this 😅
This is my code for a generic map datatype: https://github.com/JEFF-Media-GbR/MorePersistentDataTypes/blob/master/src/main/java/com/jeff_media/morepersistentdatatypes/datatypes/collections/MapDataType.java
and here's the EnumMap in specific: https://github.com/JEFF-Media-GbR/MorePersistentDataTypes/blob/144995766335727fc6050c2d29b511a0d4103400/src/main/java/com/jeff_media/morepersistentdatatypes/DataType.java#L500
np 🙂
so basically I create two PersistentDataContainers, one holding the keys, another one holding the values. Both are mapped using integer indexes as namespacedkeys. Of course the actual Map datatype then doesn't simply accept the actual key/value type, but again a PersistentDataType<?,K> or <?,V>
i dont understand that
How would I set food level to whatever user the player enters for the second argument? /feed <Player>, I have the logic I just don't know how to make the second argument the player object, I also tried casting the arguments into player obj
but if it works
Let me show you the console output
Bukkit.getPlayer(args[0]);
will get the player whose name matches the first word entered after /feed
ty
I also have a question
is the arguments at index 0 just /feed or is it index 1 for the second argument, player
and first argument is the command right?
oh I see
command is its own variable, label or Command#getName()
arguments are whatever is after
right
okay makes sense, thanks
if the command is typed and there are no arguments then is arguments null?
nope its just an empty array
Oh dang, okay then
if (args.length == 0)
Yeah that's what I got so far
@quaint mantle
this is the result of this:
@Override
public boolean onCommand( CommandSender sender, Command command, String s, String[] strings) {
EnumMap<Material,Integer> map = new EnumMap<>(Material.class);
map.put(Material.DIRT, 1);
map.put(Material.STONE, 2);
map.put(Material.GRASS, 3);
Player player = (Player) sender;
// Save the map
player.getPersistentDataContainer().set(new NamespacedKey(Test.this,"test"), DataType.asEnumMap(Material.class, DataType.INTEGER),map);
return true;
}
(without the "chestsort" part ofc)
so "k:1" = key 1 = "DIRT", "v:1" = value 1 = 1 as integer
and so on
weird
i mean im pretty sure we got the same idea
you have to imagine that both key and value could be ANYTHING, even an itemstack or whatever, so I'm not simply mapping stuff to a number but create basically a pair of "integer-based" pdc tags for every key and every value
Player typedUser = Bukkit.getPlayer(args[0]);
whenever I use this right it says args[0]
it says 0 is out of array bounds
Map<String, Integer> map = new HashMap<>();
map.put("hi", 5);
# PDC in YAML format
# PersistentDataType.STRING
namespaced-key-params: "String:Integer"
# PersistentDataType.TAG_CONTAINER_ARRAY
namespaced-key-entries:
ive gotten this far
if 0 is out of bounds, then it'sb ecfause you haven't entered any name
this could go about serialization or trying to fuck with pdcs
serialization is better
so i'd just store strings tupled with their type
basically just json
in a pdc string
yeah it just says its out of bounds in my ide, even though its supposed to getPlayer(whatevertheytype)
but what if you now wanna store something like a Map<ItemStack,LinkedHashMap<Material,Map<Integer,ItemMeta>>> @quaint mantle ?
I mean noone will ever need it but I wanted to use this to learn about generics so I wanted to make this work with EVERYTHING 😄
good luck
it's already done since 3 or 4 weeks
erm
yes
obviously
read your code line by line
you do this: "if no args were entered, get the first argument"
there obviously is no first argument if there is none
/feed -> args.length == 0
/feed mfnalex-> args.length == 1
I was told the first argument was what they typed after command🤷♂️
It is.
It is the first argument, but you have to remember that java uses zero based arrays.
Yeah its the first index
So the first element of the array starts at 0 instead of 1
{} = empty (0 elements)
{"mfnalex"} = 1 element, so the "biggest" index you can access is 0
{"mfnalex","someoneelse"} = 2 elements, so the "biggest" index you can access is 1
ah I see I was confused
["Bob", "Mary", "Joe"]
^ ^ ^
INDEX 0 1 2
LENGTH 3
I was thinking it was like that but then got confused because I thought the second arg was starting at 0,
Yeah Ik
you said player was 0
@EventHandler
public void onPlayerJoin(@NotNull PlayerJoinEvent event) {
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
SkullMeta meta = (SkullMeta) skull.getItemMeta();
meta.setOwningPlayer(Bukkit.getOfflinePlayer(UUID.fromString("e3b94eb5-2386-4e25-8cdf-c6652677b12b")));
skull.setItemMeta(meta);
event.getPlayer().getInventory().setItemInMainHand(skull);
}
Whenever I do this, I get a default head
/feed <player> player is actually 1
no
no...
args = ARGUMENTS
it's like this:
/<command> <arguments...>
just look at the onCommand method
Okay so
The command is excluded from the arguments array. It's technically part of the array, but it's removed because of the implementation,
it has
- the sender (player who entered the command)
- the command (e.g. "feed")
- the alias they used for this command (e.g. "feedplayer")
- the arguments, so everything they entered AFTER /<alias>
/feed <some_arg>
^ ^
label |
args[0]
what is it supposed to do? has the player with that UUID ever joined your server?
I forgot the length method starts at 1
length is just like normal counting
you would love lua
I think you're still confused, otherwise you would have checked if length is 2 and not 0 while you should have checked for ">1" instead of "== 0" 😄
actually I have checked that already above I just never realized it was working already
I forgot all about length starting at 1 🤣 my brain is dying tonight
No, do they have to?
Should I use a PlayerProfile then?
You're going to have to if they haven't joined before.
Or maybe it's the GameProfile
yes, they have to have joined at least once
you can use a base64 texture though
I always use this from my lib:
https://github.com/JEFF-Media-GbR/JeffLib/blob/master/core/src/main/java/de/jeff_media/jefflib/SkullUtils.java
Ok, how do I turn a UUID into a PlayerProfile?
are you on 1.18.1+?
hello, got my config and scoreboard sorted but now how would i get the lines of my config into the according lines/score in the scoreboard
yes
Offline skins are annoying. I swear older versions just worked when it came to this. Now, you have to make a GameProfile, make a request to mojang servers, populate said GameProfile with the results, then you can get the texture.
tbh imho copy pasting the part from my lib is the easiest way, then just use the base64 strings from minecraftheads.net or whatever it's called
wtf
the PlayerProfile api is nice but also a bit weird
I think he wants to get actual player heads.
e.g. you have to provide a link to the minecraft textures server
Im taking a look at your lib and this shit seems so complicated
its just showing [] but idk where tf to began with multiple lines on the config and putting them in the scoreboard
do you know the differences between scoreboards, objectives and scores?
well objective is the title i think
score is like the main bit
with text n stuff
and scoreboard is like the board
IIRC people mostly abuse the score to sort the lines
while objective is the actual text
oh yeye
e.g. a scoreboard like this:
Money: 37$ 1
Your name: mfnalex 2
this scoreboard has two objectives, called "Money: XX$" and "Your name: mfnalex"
the score of the objectives are only used to sort the lines
@tender shard I'm confused, your lib uses offline players too?
oh ye
yes but only if you want that. if you want to use textures of players who have never joined before, you have to pass the base64 string instead
so how would i like split up a list into different scores so its on different lines
loop through your list of strings. e.g. imagine this is your list:
- "first line"
- "second line"
ye
create a new objective called "first line" and give it score 2
create a new objective called "second line" and give it score 1
Im just a bit confused what the base64 string is
basically the top line has to have the highest score
https://minecraft-heads.com/custom-heads/decoration/51720-orb-yellow scroll to the bottom. there's a field "value". that's the base64 thing
The base64 string is just an encoded string that represents a texture.
ok
Also why the random UUID?
exactly. the random UUID is to not mess up profiles of players who are actually on your server
I still wonder - why do you need textures of players who never joined your server, if it's not meant to be a "custom" texture?
like e.g. you will never need the skin of "mfnalex" if I never joined your server. but obviously you might want to use a custom texture from minecraft-heads.com
so I don't really understand what you are actually trying to do
yeah but they need the texture of a player from their UUID while that player has never joined
at least that's how I understood it
I want set up armor stands thats all
I'm pretty sure they could also request the online uuid for said player when they make the request to mojang servers,
its for a feature on my server
so you do want CUSTOM head textures, and not the texture that a player with a specific UUID who never joined your server currently has, right?
alright i have
for(String entry : Config.get().getStringList("scoreboard")){
}```
how would i get each line of the string
you already have it inside "entry"
okay for the last time then: use the base64 value that you find on minecraft-heads.com at the bottom called "value"
have what
im aware
you should definitely look at some basic java tutorials if you don't know how to loop over a list
ye prolly
Im back again. Im getting this error when compiling? Unsupported class file major version 60 Im guessing its my java version but I've also tried up to 18 and still have the issue
are you using the maven-shade-plugin in your pom.xml?
I had a blacklist plugin that would show the player's heads in a GUI. (For management purposes) The issue arose when it needed to be added to multiple servers. So there could be valid reasons for wanting offline player skins who have never joined before.
no maven-compiler-plugin
send the full maven error log
click on the top most thing, the one I marked in red
then ?paste the full console output
because the "Unsupported class file" message can have many reasons
@tender shard com.mojang.authlib.GameProfile Where do I get this import
you have to update your maven-shade-plugin to at least version 3.3.0-SNAPSHOT
what MC version?
That's either from NMS or the remapped jar.
nope. it's in it's own lib meanwhile, called com.mojang.authlib
one has to manually install it using mvn install:install-file
ok, well you don't have to manually install it. just add the mojang maven repo to your pom and the dependency that way
oh yeah that works too, I didn't know they have a public repo
Are you sure? Because I don't even have that repo in my pom and GameProfile is just available to me.
if you are using nms you've got it too cause its a dependency for the server
That's what I was getting at.
oh you're right, in the remapped version it is included. it's simply the "obfuscated" spigot.jar that doesn't have it included
but the api doesnt depend on it
so you can add it if you dont want to depend on the server
1.18.2
repo: https://libraries.minecraft.net/
coords: com.mojang:authlib:1.5.25
I figured it was NMS as I noticed it was available with it before the mappings came along.
yeah either add this ^
or switch to "spigot" as dependency instead of "spigot-api"
I just so happen to always compile craftbukkit and have the remapped versions. 😛
I got something mixed up in my head. It was those people who are NOT using maven who had to manually add the authlib as dependency
because of the whole "bootstrap .jar" stuff
as I said, change "maven-shade-plugin" to version "3.3.0-SNAPSHOT" or later in your pom.xml. you might also need to add the proper plugin repository though
so you might have to add this too:
<pluginRepositories>
<pluginRepository>
<id>apache.snapshots</id>
<url>https://repository.apache.org/snapshots/</url>
</pluginRepository>
</pluginRepositories>
if you don't get it to work, ?paste your pom.xml
I changed the "maven-shade-plugin" to 3.3.0 and it compiles and works!
perfect
I wasn't sure whether 3.3.0 was already released
I still use 3.3.0-SNAPSHOT everywhere so that's why I mentioned the plugin repositry 😛
so how do I get this library?
?bt
thx
buildtools is the tool that "builds"/compiles spigot on your PC
I have a plugin on intellij that does that for me
as an alternative, you can just add my library to your dependency section, then you can directly use SkullUtils
Something that's been bugging me for a while. Why is it that my IDE gives this error, but still compiles? I have multiple java versions installed. (Java 8, 11, 16, and 17) My IDE is set to use the Java 16 SDK, I'm telling maven to compile against Java 8 and that the project source is Java 8. Yet, it still compiles successfully.
I'm testing the plugin on 1.18.2 so, I need java 16. I'm assuming that my jar file wouldn't actually work on a Java 8 server if it reached this line of code. Haven't tested that, but why is it compiling?
switch to java 8 and it won't compile
your .jar would not run on java 1.8
btw you do not NEED java 16 for a 1.18 plugin
simply remove the charset and you get rid of that warning
or better
replace "StandardCharsets.UTF8" with a string "UTF-8"
StandardCharsets is Java 7, Alex
Actually wait no
java.nio.charset was added as early as Java 4
it is, so?
it's not part of URLDecoder constructor in java 8
erm I mean
of the decode() method
@tender shard https://www.spigotmc.org/wiki/buildtools/#1-18-2 This seems to be giving me spigot but I want paper, how can I change this
java 8 expects a String as charset in java 8 @lavish hemlock
java 16+ also stills accepts the string
so if they are compiling for java 8 anyway, they should also use the string
you don't need paper for this
but I want paper
either listen to me or go ask at paper's discord
banned 🥲
Doesn't the spigot jar post 1.17 use java 16 as the minimum and if it does, wouldn't that mean that plugins should update to Java 16? Wouldn't the api take advantage of the new features?
ill just figure it out myself
MC 1.17 requires java 16+ to run. MC 1.18 requires java 17+ to run. that doesn't mean that it won't run plugins compiled for java 1.5
or you just listen to me, run buildtools for 1.18.2 once, then add spigot as dependency to your pom and you're done
Oh right. I forgot about the forwards compatibility aspect of Java for a second there. 😛
I compile ALL my plugins for java 8, using only java 8 or earlier API, and that runs fine on java 17. java 17 can easily run java 8 code. it's just that minecraft itself now requires java 17 because the server itself uses some modern features
so yeah you should either not compile for java 8, or stop using java 10+ features 😛
Well, I'm trying to move past java 8, but I need to get a couple more updates out first before I can make the full transition.
for now you can easily replace StandardCharsets.UTF_8 with either StandardCharsets.UTF_8.name() or simply replace it with a string "UTF-8"
Gotcha. It's weird having multiple versions installed. The new switch statement format prevented me from compiling, which I kinda expected, but this one was weird to me because, normally, when any type of error shows up, it just doesn't compile.
yeah that's because you weren't using a new "language feature" with the Charset thingy
the new switch cannot be translated to a java 8 source file since that is a language feature only available in java 14+
but it's no problem to compile against a method that's not included in an older JDK
it would simply throw a NoSuchMethodError at runtime on java 8
but since you used java 16, it compiled fine, even to a java 8 class file
I can't find the proper words to explain it, I hope you get what I'm trying to say lol
I think it makes more sense now. It's just a little weird that you are allowed to do that.
yeah well, it has to do with how bytecode works
the bytecode simply sees "get the method called "decode(String, StandardCharset)" and call it using the following params: ..."
javac is invoked using java 16 so it sees that method
so it's like forgetting to shade a library when you run that in java 8 then
but obviously calling a method is no different in java 8 than in java 16
that's why it compiles fine
That's something else that I'm wondering about though. I thought that the point of defining this
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
In the pom would force compilation in the defined java version.
oh no, if you look at your maven log, you'll see that it used java 16 or whatever you set in your IDE to call javac
but I want paper, so ill figure it out <3
you have no idea what you are talking about
you can use paper all you want
doesn't mean you need it as dependency
you obviously don't listen to me anyway so feel free to seek help from someone else
this simply compiles the file in a format that's understandable for java 8
Yea, just looked at the log. It's using java 16.
it does NOT make sure that all those methods are also there. after all, you could have compiled against a "runtime dependency" like spigot
obviously org.bukkit.craftbukkit.CraftServer is also not present in the JDK 8 but you can still compile your code, since the compiler has it as runtime dependency 🙂
and the JDK 16 compiler also had that method as "runtime dependency"
I can't explain it better right now, it's too late for that 😄
No worries. I get the gist of it. I also now understand what those flags actually do.
:3
if u want paper with nms for versions 1.16+, ur required to use gradle with their paperweight userdev plugin
can someone tell me how to make [org.bukkit.permissions.PermissionAttachmentInfo@5c4ccb0d] PermissionAttachmentInfo show up as a string inside my db instead of the object name
I tried setting the object to a string, adding the object to an array, and multiple things I just don't know what will work now
json serialize/deserialize
use gson methinks
what r u trying to do tho
im trying to get all of a users permissions and store them in a database
however as a string
not the object
Set<PermissionAttachmentInfo> playerPermissions = event.getPlayer().getEffectivePermissions();
i think its better to store each permission node and its boolean value in a db
however if u really want to use permissionattachmentinfo just serialize using gson
when doing Block#setType is there any kind of world update i need to do. or chunk update?
how
I use getEffectivePermissions to get all permissions that a user has, I try to parse it but it doesn't work so how would I store each permission node
I might have just figured it out
yeah no lol it always outputs as
[org.bukkit.permissions.PermissionAttachmentInfo@333d287f, org.bukkit.permissions.PermissionAttachmentInfo@3c8e3f0d,
it auto updates all that for you
I quit development a while ago but I'm tempted to get back into it. However every time I've had this itch it's ended up in me leaving again due to burnout. Not to mention the fact that I've probs forgot 90% of everything I knew and no longer own a vps or anything like that. Is it worth it? Still considering
This ain't paper discord
is there a packet for suggesting commands to players without them needing to click on a basecomponent with an inbuilt suggest feat?
how can I check if a player is looking away from another player by at least 90 degrees?
what's the event for when a player's main hand item is changed? like if they scrolled through their hotbar, or if the item broken, or if they swapped the item with another item, etc etc
PlayerItemHeldEvent
not sure which version tho
thx
np
can i input object by scanner?
ItemStack playerHead = new ItemStack(Material.PLAYER_HEAD);
UUID hashAsId = new UUID(base64.hashCode(), base64.hashCode());
return Bukkit.getUnsafe().modifyItemStack(playerHead,
"{SkullOwner:{Id:\"" + hashAsId + "\",Properties:{textures:[{Value:\"" + base64 + "\"}]}}}"
);
Whats a non deprecated way of doing this?
What version are you on
It's the lastest
So 1.18.2
yessir
declaration: package: org.bukkit.inventory.meta, interface: SkullMeta
To get skull meta simply cast ItemMeta
How would I turn my base64 texture into a PlayerProfile?
Start by creating a PlayerProfile instance. Then get the PlayerTextures from it and use setSkin
Any chance you could run me through how to make a PlayerProfile instance?
Thats what I've been struggling with... I just have no clue how to do that and I've been digging in the docs for a bit
PlayerProfile is an interface though, how to I get an instance of one
getTextures will return an instance of it
of a PlayerProfile?
from the docs it appears to return a PlayerTextures object
oh you're talking about the PlayerProfile. oops read the top of the javadoc link I sent earlier
declaration: package: org.bukkit.profile, interface: PlayerProfile
Didn't sent it ;/
bump
ah perfect
Now I have my PlayerProfile.. now what
now call getTextures on it to get the texture instance
okie dokie
Then you have the setSkin method to set the skin
If you only have base64 you will need to decode it and get the link to the skin
player.getEyeLocation().getDirection()
that will give you the vector of the direction they're looking in I think
then just compare
do some trig
if you know the locations of the two players
I know the locations of both players, just have no idea how to go on about it
have you done trig before?
tried exactly that with #getLocation
nope
use getEyeLocation if you want to get the direction they're pointing in I think?
ah
Yeah
i thought Eyelocation was the location of the camera, and getTargetBlock was the location where they're looking at?
yes but .getDirection() on eyeLocation gives the direction they're pointing
oh, okay
how do I do that :|
you then know the locations between them, the distances, and the angles in which they are facing
The result may end up as a json but it shouldn't be hard for you to get the texture link out of it
ty ty
what you want to do is get a vector going from player A to player B
by subtracting the distances between them
find the angle at which that vector is pointing
get the angle at which the player in pointing
compare
that's a lot, but I'll try my best
yeah it could be fairly challenging
vector math is too much for me
right
it's not too challenging
in a sense they're basically just co-ordinates
things do get slightly more complicated when you go into 3d tho
shouldn't File.pathSeparator be a \?
Path seperator is the seperator that is used between two paths
you likely want File.fileSeperator or something like that
actually idk
is there a way to overwrite the default world generator?
?jd-s
What can I do to Item getid
how do I do that 🤔
Java version?
17
and would this change depending on OS?
so do I only need to escape it if it's a backslash?
cause I don't think all OSs use a backslah
I already tried that but it is still not working :/ This method does literally nothing
Okay, there is https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html#translateEscapes() and I swear there is a method that is doing the opposite of it - which is the method you need but I have no luck in finding it
Yeah, that is probably a better way of doing it considering that not all java escapes are regex escapes
Idk what you're doing though
Using the path/file api to deal with folders makes more sense surely
Another way would be to use
Path path = dataFolder.toPath();
List<String> xyz = new ArrayList<>();
for (Path x : path) {
xyz.add(x.toString());
}
If I am not mistaken
quite possibly? I don't know much about it so ig I can look it up
What are you trying to do
so I'm making minigame worlds
I want to have them organised
so a folder for all maps
then sub folders for each game
then I need a folder for temp worlds
cause my plan is for when a minigames starts, I copy the world into the temp folder
so I can have multiple instances of the same world
then delete it when it's done
Then I am not sure why you need the split operation there.
yeah probably not
I was having a look at this
which used splitting
but it doesn't look like a very good resource
I thought I'd just have a look anyway
so for something like this, how can I add to the end of it?
I'd like to create a new folder called 'maps'
if i instantiate an inventory in a local scope like this ```java
Inventory inv = Bukkit.createInventory(null, 9*5, ChatColor.DARK_RED + "TEST");
inv.setContents(((Player)sender).getInventory().getContents());
((Player)sender).openInventory(inv);
Wdym GC?
garbage collected?
or is the inventory deleted as soon as it gets out of scope and all opened instances are client sided?
Oooh in that sense
I think that the object will still be there even if nobody has it opened
causing a memory leak
?
how do i properly close/delete/GC an inventory ive created myself in a local scale?
once the last inv viewer closes it
What can I do to Item getid help me please
what do you mean with id?
iteminhand id
why would it not get GC'd after the inventory is no longer used?
do you mean the item name, 1.7 number id, ItemStack or material?
Refers to the id of the item at hand.
becase i create an inventory in a local scale on command and let say the admin who has performed the command open the inventory right? then the inventory goes out of scale on exiting the command callback. yet the player still has an open instance of that inventory and its still passed to the InventoryClickEvent properly meaning even tho it went out of scope originally, its still existant.
As soon as an object is not reachable and does not have a finalizer block it will get GC'ed unless you are using the epsilon garbage collector
so i wonder how to properly treat self created inventories so i dont cause a memory leak
I have no idea what youre talking about
material
ItemStack.getType()
ItemStack
The inventory is still reachable via some method I am not bothered to look up, but as soon as the player closes the inventory it will not be reachable
You don't. This is not C/C++. As long as you do not put it in any collection where it will never get removed you are fine
so its a safe method and the inv gets GC'ed as soon as the last inventory viewer is requesting the close inventory package?
not requesting, but actually closed
kk
Also your inventory even if it was to never get GC'd would only represent a tiny portion on the stuff that is actually leaking
in newer minecraft versions there's a method to get the center of a block location, it's block.getLocation().toCenterLocation();
i can't find a way to get this in older versions tho, any help?
haha well im still brain damaged from it. C/C++ is also idiot safe if ur not using the new keyword, unless that is ur working with say graphics libraries which utilize dynamic memory allocation like DX
Floor the coords and add 0.5
and since certain methods in java are written low level accessing the system and user dll iirc
im never 100% certain
How do you show it as a number of items
if I understand you correctly, you're talking about an ItemStack
that would be the amount of the itemstack
yea but wyd if u cross the 1mrd coord and no longer can go float 😉
not really a satisfying solution though
memory clogging up
If I have an abstract static field will each child class have their own version of the static field? My current understanding is that a regular static field will only exist once between inherited classes. For example child.staticField is equivalent to parent.staticField, but is this the case for abstract?
👌
u only create child + parent implementations when u dont override them
It's a double
and then u access them using this.foo() and super.foo() with super being the parental class @supple elk
I mean like diamond sword ro id 276 😅
didn't even need to floor, thanks
and iirc abstract is forcing u to override them
are you on 1.7 server?
1.18
because unless you're using worldedit or something like that, number ids are not used anymore, correct me if im wrong
ohhh
what would you need them for?
No thanks for the answer 👍
no problem
Just use the epsilon garbage collector. Your server will die from an OOM within a minute
I'm trying to store metadata about a class. I have an abstract game class which all different games will implement, then a particular instance of a minigame will be one instance of a child class. I need metadata about each game class though, like the name of the game, display icon etc. Currently I have a static abstract field for each piece of meta data, however this is difficult to access when there is no specific instance of the class available. Any recommendations on how to do this?
for example:
I could do game.getField("name")
Game.name
doesn't work
it does, it's static
oh wait
The real question is why is it static
nah they want to have it for every class i think
yeah
So remove static
each child class needs to have a different val
just do getField() i guess
but it's the same across all instances
that is kind of an antipattern
How many game instances should there be?
bukkit does the same thing with the HandlerList thing on events
any number
Just have a getName method or smth and let each child class specify
If there is only one you might as well use a thread local :P
ah
yeah that's prob the thing
Still a dumb solution
bruh i do it too
hey I've also got a question,
where should I put ChatColor.translateAlternateColorCodes() in here cuz wherever I do I get errors because the said method requires me to provide a string but I have an array list (lores from config).
ArrayList<String> lore = (ArrayList<String>) main.getConfig().getStringList("items.0.lore");
assert meta != null;
meta.setLore(lore);
hang on this still doesn't work I don't think
you need to loop over the list and build a new one with the translated codes
cause I need to be able to access the method without an instance of the class
no because you need it on the class right
not on the instance
yeah
There is no need for obtaining the handler list class that way anyways (well there is, but only because of strange API).
hold on
uh reflection it is then I guess
oh well either way this sounds like a bad idea
MBassador for example can use ANY object as an event while still being able to use the object hierarchy
you can do it quite simply with
List<String> translatedLore = lore.stream().map(line -> ChatColor.translateAlternateColorCodes('&', line)).collect(Collectors.toList());
@paper falcon
how would you go about the problem then?
think that should work
Same as I said
I'm open to suggestions on how to structure it properly
Just create an instance and get it
but an instance of a game is a physical game in progress
Are you sure that you cannot create an instance of the class at that point?
yes
in a menu I need to display which games exist
meaning I need to know the name of a game and a display icon
make a boolean of started and if its false the game isnt started
And then loop through the listof games and from there filter by true started booleans
boom, running games
that did the trick, thank you very much 🙂
Yeah then it is quite clear that you will have a "GameFactory" class that will be able to create games
np
^
but then you need an instance right
annotations in java are fun
So like your game meta idea but it is the only way to create a game
and then you can just do
public abstract String getName();
no cause there still no instances in existance
it shows the possible games
I only really use annotations for ASM Transforming these days or for event handling or for NotNull/Nullable and other contracts
so for example say I have 3 different games, tnt run, survival games and skywars
there can be multiple instances of each
but I need to know the metadata about each without there being any instances
the name of the game, icon, etc
cause an instance is a physical game in progress
Just use an instance
public interface GameFactory {
public Game createGame();
public String getName();
}
public interface Game {
public GameFactory getFactory();
}
is how I would do it
You will have them stored somewhere
been playing around with them today for a command lib I'm working on
havent really touched them too much beforehand
this feels like a strange solution to me
Not really
Its normally how you do things
you have a Manager of some sorts for your list of Game's
If you want a list of running games, use the running games instance?
Either way, reflection is the wrong way of doing it
I think I prefer the Factory idea
yeah ik that much
The other solution would be to have something like
public abstract class Game {
private boolean started = false;
private final String name;
private static final Map<String, ? extends Game> games = new HashMap<>();
protected Game(String name) {
this.name = name;
if (games.putIfAbsent(name, this) != null) {
throw new IllegalStateException("There is already a game with that name");
}
}
public boolean start() {
started = true;
}
public boolean end() {
started = false;
}
public String getName() {
return name;
}
public boolean isStarted() {
return started;
}
public static String getGameByName(String name) {
return games.get(name);
}
}
Not sure if you really want to put things in the map directly in the constructor
I just did that to make sure that there aren't two game instances with the same name
can i store objects in pdc?
if you serialize/deserialize them
?jd-s
thats an option yea
you could also do json
https://github.com/JEFF-Media-GbR/MorePersistentDataTypes
You can use this if you want things to be easier 🙂
?stash
hm
It can also be an int-array and anything like that
@quiet ice how is this?
so then if I want metadata I can call GameManager.getSkyWarsFactory.getMeta()
or getSkyWarsFactory.createGame() for a new game
I'd pass the factory instance through the game so it is a singleton
slight issue with that
so if I have an abstract class or an interface for the Game class
what would the method declaration be?
cause I want Skywars to return a SkywarsFactory
yes, you can simple pass that factory through the contructor of skywars
but this method also needs to be static doesn't it?
is there any like minigame api?
ughh why are abstract static methods not a thing
no matter if its static
it does cause I need an instance of the factory without an instance of a game
cause the factory is the only thing which can get me an instance of the game
why is this so confusinngg
oh wait so Game is like the game type
yes
wait
?paste
oh yea
then an instance of a Game is a physical game itself
hey, i have this code but i get an error while running it :
https://paste.md-5.net/equnohugac.java
the error :
https://paste.md-5.net/pubomuzuxe.bash
public class Map {
private final GameType type;
public Map(..., GameType type) {
this.type = type;
}
/* some function */ {
String name = type.getName();
}
}
public class Game {
private final GameType type;
}
public class GameType<T extends Game> {
private final Class<? extends Game> runtimeType;
private final String name;
public GameType(...) { /* do init */ }
public String getName() {
return name;
}
public abstract T createGame(...);
}
``` @supple elk something like this would work
ah ok
Geol was suggesting that I get the GameType from the Game itself
but that doesn't seem possible
why call it factory tho
cause it creates a Game ig?
mk
nah not really but it might be useful
mk
it means I have to pass in the same info twice though
so I can't do Class<? extends Game?> runtimeType = G
type erasure
yeah
yes
I'm then using a singleton manager to store an instance of each factory
or gametype in this case
do you think an enum might be useful?
okay
I think the system I have rn should work fine
yeah
also maybe store all running games in the game manager
it really doesnt matter but i just thought it made more sense
it does
If I'm passing it into the map
kinda weird to pass in a factory to the map or whatever
true
if youre going to make it available as an api or just want it to be clear i would use GameType yeah
I mean I could make it as an API ig
I'm basically building all the foundational work atm to make minigames
I've done NPCS
nice
a straight projectile
My plan was just to make minigames to play with friends
ah
but maybe I should separate API and implementation
hmm
there is one thing I don't like currently tho
which is that every new gameType I create I have to declare a new static field in the manager
yeah
in your onEnable
currently it's not gonna work as an API
as u have to add that static field into the class
can i somehow create an inventory thats identical to creative/survival inventory a player opens when pressing E?
Don't think so
yeah
but ur right it is very useful to have 🤔
but if you want commands like /creategame skywars you might want to store them in a map
what would be the key?
What are you trying to implement?
like the class of the Game?
No, just generally
<<? extends Game>, GameType>
Will classes extending JavaPlugin get a Constructor called if they have one?
r u talking to me?
Yes
public class GameType {
// ...
private final String id;
public String getId() {
return id;
}
}
public class GameManager {
private final Map<String, GameType> typesById = new HashMap<>();
public void registerType(GameType type) {
gamesById.put(type.getId(), type);
}
}
smth like this
I guess you could use an enum
ah ok
perhaps? Though can that be added too easily?
Yes
example plz