#help-development
1 messages · Page 526 of 1
you can do that in the duels class
I don't think you seem to understand what I am saying
you know what parameters are right?
Yes
can there be more than one duel happening at a time?
and you want me to initilize the duel
it appears so
when both player objects are avalible
not rn
i wouldnt mind keeping it open for later edits and expantins
Then you needjava // add all players currently in a duel. Set<UUID> participants = new HashSet<>(); Set<Duel> activeDuels = new HashSet<>();
From my limited search: If you can give the player a resourcepack then create an item model of the shape you want but with invisible texture.
Not sure if there is other way.
a Duel class which takes two player UUIDs
public class Duel {
public Duel(Player player1, Player player2) {
}
now, because the Duel class requires 2 player objects you can't create a Duel object IE new Duel() unless you pass in 2 player objects
as I suggested before it could be a record
you could use UUID's as well
didnt someone tell met not to touch records till im better at java
how to force a player run a command even they don't have perm?
why would this be necessary?
partipants hold the duelers
so
the first person clicks, added
Hey!
I'm currently having some issues with setting a spectator target.
Basically, what I'm doing is teleport the player to the target and then set the spectator target. The target doesn't move at all, yet as soon as I set the spectator target, the camera seems to always do a 180 degree turn. Does anybody know what could cause this or how to prevent it?
(The teleport as well as the delayed task are to help with larger distances.)
Edit: tried manually rotating 180 degrees to test, but there's still rotation happening
Spigot 1.19.3 / Java 17.0.3
public void setSpectate(Player target) {
player.setGameMode(GameMode.SPECTATOR);
PotionEffect blindness = PotionEffectType.BLINDNESS.createEffect(30, 9);
PotionEffect slowness = PotionEffectType.SLOW.createEffect(30, 0);
player.addPotionEffects(Arrays.asList(blindness, slowness));
player.hidePlayer(plugin, target);
player.teleport(target.getLocation());
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> {
player.showPlayer(plugin, target);
player.setSpectatorTarget(target);
}, 10);
}
second person, added then starts
every player who enters a duel gets added to the Set, IF they are not already in it. If they are already in there then they are already in a duel
what about the logic that checks if a duel already has a opponent set
if both participants are not in teh Set you create a Duel object for them, puth both in the participants Set and add their Duel to the other Set
a set could be used, but I think it would be more appropriate to use an object that contains both players so that both things are available at the same time
and not just one and then hanging left waiting for the other
Yes you also use a Duel object
the participants contains ALL players currently in a duel.
OH, so evvery player that clicks, a set is made for them, if they are two sets, you initlize a duel object for those sets
could be 100 players in there
but it allows you to quickly check if a player is engaged in a Duel and not able to start another
slowly we are getting through to them
Your duel object contains all the code you need to manage each duel
Now I need 1 or two sets, for player 1 and 2, or one that holds both players, and adds to it.
I really do recommend that you do some more learning as well when you are not just trying to code your project
you would benefit in learning some more concepts and what not
Every concept i come accross i watch a video on, i know records, sets and maps, i also learn the funamentals of java
if you did, you would have instantly understood everything I was telling you
but that isn't the case, same with what ElgarL was saying
I didnt see what was in ur mind, anyways, i am two make one hash map and 1 set, or two sets?
that makes no sense, anyways I am out. I don't spoonfeed
your not writting the code for me
thats spoonfeeding
like, a set for both players each, or a set that contains both players?
with the amount of questions you keep asking it is almost to that point. I have nothing else to add. I have explained and told you what should be done, how you go about implementing it is up to you. We can't dictate and tell you 100% of everything
Ok, then awnser one final question, and ill figure out the rest myself
^ just this and ill be on my way
well the question is probably for ElgarL
@eternal oxide
to do what, type something into a file?
yeah ig
im sure most can manage to do that
yes so you can store the yml files you create with the file configuration in your plugin folder
How would I go about doing that?
The Configuration API is a set of tools to help developers quickly parse and emit configuration files that are human readable and editable. Despite the name, the API can easily be used to store plugin data in addition to plugin configuration. Presently only YAML configurations can be used. The API however was designed to be extensible and allow ...
I'll check it out
thanks
would it make a difference that the thing itself uses a seperate API repo?
Hi, its possible to read and call this function from a string like "SKRIPT".load() even using Reflection or something else
https://paste.md-5.net/dogucetoze.java
After all of them are loaded?
No not like that
yea i know Java doesn't work like that, but was for explaining what i meant
No because a String is a String. You would need to have some way to convert that String into whatever instance you need
Manifolddd
if (String is String) when
Jotlin in Java
Lombok has extension methods
var configB = YamlConfiguration.loadConfiguration(new File(name2));
//var configC = configA.combine(configB); ``` Is there some kind of build in method that I can use to combine 2 configs?
wdym combine?
merge
No
Nahh
That'd be crazy useless lol
you can probably write sections
Yassss
oke
I'm getting "org.bukkit.plugin.InvalidPluginException: Cannot find main class `co.uk.robuxtrex'" in console when i try start up my server. i can send code snippets if required. first time ever messing with spigot and i have basic knowledge of java (via other languages like cs)
I assume robuxtrex isn't your main class
and I hope you have more CS experience than basic unity knowledge
i taken a course on cs.
like a year ago
package uk.co.robuxtrex.permavision;
import org.bukkit.plugin.java.JavaPlugin;
public class App extends JavaPlugin {
@Override
public void onEnable() {
getLogger().info("Hello, SpigotMC!");
}
@Override
public void onDisable() {
getLogger().info("See you again, SpigotMC!");
}
}
app.java
co.uk.robuxtrex.App
^ that would be the main class
I recommend using a proper Java IDE like Intellij or Eclipse instead of vscode
so would I need to rename the app.java file to something like permavision to change it to my preferred package name (co.uk.robuxtrex.permavision) or do I have to change other stuff?
i'm recreating the maven project
it is
where would i set this
That's the format for the main class in the plugin.yml
same error this time with .Main at the end (i changed the class)
what is the file name?
Main
And directory structure?
wait there
Could you show the project view within your IDE? Right now I have no concrete idea of what you are doing
if your class is called App, the file also has to be called App.java, not Main.java
C:\Users\feder\IdeaProjects\PlaxerCore\src\main\java\org\plaxer\it\plaxercore\command\Guimenager\GuiManager.java:3:26
java: package com.mojang.authlib does not exist
C:\Users\feder\IdeaProjects\PlaxerCore\src\main\java\org\plaxer\it\plaxercore\command\Guimenager\GuiManager.java:4:37
java: package com.mojang.authlib.properties does not exist
C:\Users\feder\IdeaProjects\PlaxerCore\src\main\java\org\plaxer\it\plaxercore\command\Guimenager\GuiManager.java:62:9
java: cannot find symbol
symbol: class GameProfile
location: class org.plaxer.it.plaxercore.command.Guimenager.GuiManager
C:\Users\feder\IdeaProjects\PlaxerCore\src\main\java\org\plaxer\it\plaxercore\command\Guimenager\GuiManager.java:62:35
java: cannot find symbol
symbol: class GameProfile
location: class org.plaxer.it.plaxercore.command.Guimenager.GuiManager
C:\Users\feder\IdeaProjects\PlaxerCore\src\main\java\org\plaxer\it\plaxercore\command\Guimenager\GuiManager.java:64:53
java: cannot find symbol
symbol: class Property
location: class org.plaxer.it.plaxercore.command.Guimenager.GuiManager
how i resolve this?
marven
<repositories>
<repository>
<id>minecraft-repo</id>
<url>https://libraries.minecraft.net/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>authlib</artifactId>
<version>1.5.21</version>
<scope>provided</scope>
</dependency>
</dependencies>
there might be a newer version, haven't checked
<version>1.5.21</version> give error
reload maven
np
anybody know where I can find the JLS (doesn't matter whether version 8, 11 or 17) in one SINGLE html file? I can only find the one where you can only see one chapter at a time, but I cannot ctrl+f through that
does anyone have an idea?
lower the delay btw
I have the delay that high because if I go any lower the effects will feel to abruptly applied and removed
are you sure target is looking into the correct direction? what happens if you add a delay between showPlayer and setSpectator?
I mean I'm teleporting the player to the targets location, which includes yaw and pitch. I couldn't find any info that's saying that the yaw and pitch are not taken into account, so the direction should match 1:1 the moment I teleport the player.
Even with the added delay there's still a rotation happening
weird. what happens if target moves later, does the player always see all movements inverted?
No, movements are all correctly displayed after the spectator target is set. It's just the initial setting that's been giving me problems
tried to trial and error but ending up getting "org.bukkit.plugin.InvalidPluginException: Cannot find main class `co.uk.robuxtrex.App'" even though the main in plugin.yml is "co.uk.robuxtrex.permavision.Main" App.Java is Main.java and the class name has been changed
main.java
package co.uk.robuxtrex.permavision;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin {
@Override
public void onEnable() {
getLogger().info("Hello, SpigotMC!");
}
@Override
public void onDisable() {
getLogger().info("See you again, SpigotMC!");
}
}
here's the issue. when you do showPlayer, it spawns with default pitch/yaw or sth, because spigot first sends a "player joined" packet, and then a clientboundPlayerInfoUpdatePacket
I see, so a delay would work, it just needs to be longer. Not really something I want to do so I guess I'll have to live with the roation.
Thank you for testing this^^
when i use this.getConfig(); do I need to define the location of the configuration file in order for this to work? plus, does this need to be in the onEnable() public void
getConfig defaults to pluginDataFolder/config.yml
saveDefaultConfig grabs the embedded config.yml on your jar and saves it there
where do i make the plugindatafolder then becuase it's currently in resources
server makes it for you
getDataFolder usually defaults to plugins/<your plugin's name>
don't worry about it too much
just put your files in the resources folder
as if they were in the plugin's folder
will it just grab the yml file from there?
yeah
cool
also
where do i put the FileConfiguration config = this.getConfig();? in public void onEnable()?
wherever you're using it
alright
thank you
i'll report any problems i have here
also
is getLogger().info("Hello, SpigotMC!"); meant to print something to the console?
on enable
yes
use error instead of info, then its red lol
I'd recommend testing your stuff in a clean server
^
System.err.println ;)
the only option i have is minehut, which is just the most broken mess on earth
localhosting ??
usually what I do
I also have a free oracle vps in case I need any databases or maven repo
also, does .getList() retrieve an array from the config?
something like that
use a boundle packet
You can send a bundle packet, send spawn and rotation, and use bundle again so that both are run at the same time sequentially
so it doesn't render the flick
we love sytem
I did that on accident once, it actually works
(sent message to console on accident)
lol funny how the same project works on macOS but not on windows
does .getList() retrieve the desired array from the configuration file?
or is there another function (or whatever it's called in java) to retrieve and define an array
yes
they are called methods as they are part of a class
what keyword is used to define it? i'm using array right now and it's complaining that it's undefined (Array cannot be resolved to a typeJava(16777218))
( Array players = config.getList("players");)
show the error
Ah it's not array
use List<Object> (you can also use getStringList to get a list of strings)
Array is a reflection thing, to use arrays in java you do type[]
like int[]
"List cannot be resolved to a typeJava(16777218)"
i primarily use typescript/luau
ah
very rarely rust
Type mismatch: cannot convert from List<capture#1-of ?> to List<Object>Java(16777233)
what are you using that list for though
a list of players in the yml file to apply night vision to
which links into my next question
how do i apply an effect to a player
First you gotta have a player
^
player names
So you might want to use getStringList, change the type to List<String> and use that, i gtg now though
Alright so let's say you have something like
players:
- 'ImIllusion'
- 'IllusionTheDev'
- 'Notch'
What's the type of that list?
string list?
Are the elements strings, integers, booleans?
They are strings, alright
So in code, you'd do something like
List<String> playerNames = config.getStringList("players");
Now you have a collection of player names
Let's loop through that and get a player
for(String name : playerNames) {
Player player = Bukkit.getPlayerExact(name); // replace with getPlayer for partial matching
if(player == null) { // may be offline
continue; // don't break out of the loop, just skip to the next iteration
}
// apply effect
}
@echo basalt What about streams though?
stick to the basics
fair
streams are for people that are too eloquent to actually write a for loop
also, does .getPlayerExact() include the geysermc prefix
use streams if you know what you're doing
No clue, try and see!
nope
It just does a name match
You need to add the geyser prefix
alright
If it is a geyser player*
also Player cannot be resolved to a type? do i need to import something
yea
Alright
Now look through the player methods and see what might be useful for potions
these might help
also, couldn't you use if(!player) {} instead of if(player == null) {}?
alright
That type of comparison only works for booleans
kk
most likely .addPotionEffect()
Alright
Let's use the top method as it'll be the one most commonly used
It takes a PotionEffect as a parameter
So looking at the constructors, just pick the one you need
speaking from experience, the duration is in ticks
would PotionEffect be something like 'NIGHT_VISION' or an ID?
It's an object
Here's a sample
PotionEffectType potionType = PotionEffectType.NIGHT_VISION;
PotionEffect effect = new PotionEffect(
potionType, // night_vision
100, // 5 seconds -> 100 ticks
0 // amplifiers start at 0
);
It's ok to just have these all as a single line honestly
player.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, 100, 0));
You can set Integer.MAX_VALUE as the duration if you want
for a permanent effect
would that also re-apply the effect on death/totem used
or would i have to make an event for that
does Inventory.getSize() return: 1 or 8
how would I do that?
it returns the amount of slots
so uhh
ight
5 for hoppers, 9 for single row chests
27 for regular chests
54 for double chests
uhh
45 for players
something like that
yee ty
About time you start using google as these basics are extensively documented
yeah
personal recommendation
add spigot as the first word
and then just sum up what you're looking for in 2-3 keywords
like this
I always add spigot at the end
usually at the start narrows it down a bit more
as the initial words are prioritized a lot more
or in the middle: how to listen SPIGOT to events
PotionEffectType is not an enum
yeah I hate it
really?
Enums are not expandable
Minecraft is increasingly becoming more expandable
The Keyed Interface should get a "getByKey" in that case.
well
it has been announced like in 1.17 but still hasn't happened
It's super annoying to instantiate dynamically
Which ones?
Registry.MATERIAL.get(someNamespacedKey)
bukkit registries
Yeah that's not the interface though
Some classes have a direct getByKey
I stumbled over that with dynamic configurations
Hmm I might be able to work with the registry then instead of doing this
if (Keyed.class.isAssignableFrom(type)) {
try {
Field field = type.getField(s.toUpperCase());
if (!asString) {
return field.get(null);
}
return s.toUpperCase();
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) {
}
}
💀
yeah that's why I wanted a getByKey in the interface
The class is dynamic
So I can only check for "Keyed"
when i'm making a new listener, it's complaining that the DeathListener doesn't exist!
getServer().getPluginManager().registerEvents(new DeathListener(), this);
DeathListener cannot be resolved to a typeJava(16777218)
Do you have a class called DeathListener
Definitly would make the parsing of string to object less painful
oh shoot
I would just use registry.match
So just get the registry via reflection and then use match?
why not just get the registry using the class name?
I’m curious what you have where a user can input any keyed object
It's not the user. It's an engine and developers can create fields of any class
therefore I have to create them by reflection based on a string input from the configuration
the enchantment registry just falls back to methods in Enchamtent lol
Basically like this. I check the type of the annotated fields and I have to instantiate them using a string input
And since PotionEffectType is not an enum I had to do this annoying Keyed workaround
How can I do a counter when the player click it add +1 to a var?
is a FileConfiguration decleration mutable?
Should be.
Does every Keyed Object have a Registry.NAME field? In that case I might work with that and call get of the Registry instead.
thanks
Would still require reflection to access the Registry but would look cleaner
I think so
Make a global variable and modify it when the player clicks.
Aight I'll rework that part then
PotionEffectType does not have a registry
Yikes nvm then
weird because everything else I know is Keyed does have a registry
however I think I checked on 1.19.3, not 1.19.4
these are all registries
I'll stick with getting the static fields then. And I really hope every class implementing Keyed (that's not an enum) does have them lol
Orrr they actually improve the Keyed Interface. That would be a blessing
There is the event when a player do a left click (in the air or other) ?
PlayerInteractEvent with some checks
PlayerInteractEvent can be used ?
Alr.
So, I am trying to wait 1s before get the CPS of the player in 1s, is it good for you ?
https://sourceb.in/jFrqXXUg0F
@EventHandler
public void onInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
Action action = event.getAction();
ItemStack item = event.getItem();
FileConfiguration config = this.plugin.getConfig();
...
if (config.getBoolean("cps." + player.getUniqueId() + ".enabled")) {
int currentCounter = config.getInt("cps." + player.getUniqueId() + ".counter");
config.set("cps." + player.getUniqueId() + ".counter", currentCounter + 1);
}
}
I would add an access layer to your configuration
also don't forget to save the config (not in the event though)
Config is not a place to store a statistic like CPS
Ah yes.
Well if he needs to persist it for some reason it is. Sure he could do a map instead of directly setting it to the config but as long as he doesn't save the config is also a map
Does he need the statisitic when offline?
save map on disable and refresh it on enable
🤷♂️ probably persisted over restarts
A lot of plugins use "config" files for data. Not the standard plugin config though, true
yeah bad plugins 😉
Essentials did that for a long time aswell and yet still it was quite popular
no but in yml files in the plugin folder
What?
yes, yaml is fine
that's why I said "config" files
ah
A better approach is to make a Hashmap that stores the CPS of the player. Then onEnable and onDisable you can save/read the stored data
Shoudl probably clarify with "custom" config 😉
Either by looping or serialization
A config is a hashmap after it got loaded
..
doing a Map would be best
Why it's deprecated ? ```java
Bukkit.getScheduler().runTaskTimer(plugin, new BukkitRunnable() {
@Override
public void run() {
config.set("cps." + target.getUniqueId() + ".enabled", true);
}
}, 0, 20);
Sure you could do another map to put back into that map. I don't know if there's a huge benefit though.
new BukkitRunnable() -> {
UUID is already ConfigurationSerializable so you can just .set("path", map)
What?
For that many accesses it's probably worth it. Generally idk about caching already cached config/file data.
read the javadocs
Because it's unnecessary. You either use a BukkitRunnable on its own or you use the scheduler with a Runnable
I would personally opt for the Runnable in this case because you're not cancelling it
Bukkit.getScheduler().runTaskTimer(plugin, () -> {
config.set("cps." + target.getUniqueId() + ".enabled", true);
}, 0, 20);```
Choco will there be an improvement for the Keyed interface for 1.20?
a getByKey
That's why Registry exists
Received the error java.lang.IllegalArgumentException: Plugin already initialized! on plugin startup in my server console. Is having two onEnable()'s in two different files the issue?
Well how do I dynamically get a registry based on a Class that implements Keyed?
I think you have a backwards design
🤷♂️ it's not noted depracated in the IDE + in the docs. https://gyazo.com/47fb42575e78f993d20dde608e91cdfa
Only one class should extend JavaPlugin
Backwards as in?
okay. how do I grab the config file from two different files?
that's the RUnnable one. Not the BukkitRunnable
?di
Guide to dependency injection: https://www.spigotmc.org/wiki/using-dependency-injection/
Ah, and how I stop it?
Break?
Backwards as in you're trying to get the Registry from a Keyed, which just isn't really possible
call cancel() on the returned BukkitTask
Well I wanted to create an api that would fill those fields based on a string input. Therefore I kinda need to fill that field just by knowing the Class implements Keyed
if you need to do it from within the runnable, either use a BukkitRunnable, or use the Scheduler where you pass in a Consumer<BukkitTask> instead of a Runnable and then call cancel there
I can workaround it with reflection but I'd prefer a cleaner way
And even with reflection there's no clean way and I just have to expect that the Class implementing Keyed is either an enum or has constants for its values
Also PotionEffectType doesn't have a Registry for some reason
Uh what?
Is there any reason you don't just assign the field a default value? Why does that have to come from the annotation?
Because it's configurable
The default value is configurable? How so? You're hard-coding it in the annotation too
No that's a default. Therefore it can change.
@ConfigurableValue(defaultValue = "REGENERATION")
private PotionEffectType effect;
@ConfigurableValue
private PotionEffectType effect = PotionEffectType.REGENERATION;
imo the second one makes more sense
There's no reason to make your default value a string in an unrelated annotation
You can still set the effect value to whatever you want, or leave it as is if it's not set in the config
// Scheduler + Consumer<BukkitTask>:
Bukkit.getScheduler().runTaskTimer(this, task -> {
if(something) {
task.cancel();
}
}, 1, 1);
// or BukkitRunnable without scheduler
new BukkitRunnable() {
@Override
public void run() {
if(something) {
this.cancel();
}
}
}.runTaskTimer(this, 1, 1);
Alright thanks.
True removing the default value would make sense.
I'd still require a way to overwrite it with another value. That would lead to the same problem
Sure. Though there's not really much you can do about that unless you hard-code in the registries into your annotation processor
Which is definitely an option. Not pretty, but an option
What about PotionEffectType? There's no registry
And it's not an enum. And it implements Keyed
That's why I currently workarounded it by expecting constant fields and accessing those by reflection.
It's not clean though.
s is a String
if (Keyed.class.isAssignableFrom(type)) {
try {
Field field = type.getField(s.toUpperCase());
return field.get(null);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) {
}
}
Is there some plugin that is a addon to griefprivention and make it so players can transfer claimblocks to each others? if not how do i get the 2 args? tag me
Hmm so either hardcode all registries which would break on updates or get the registry by reflection just like I'm getting the constants in the code I just pasted
Or hardcode them and back it up with reflection
Better imo to hardcode them in this instance
Reflection is about as maintainable as hardcoding is here
private void cpsPlayer(Main plugin, Player player, Player target, FileConfiguration config) {
player.sendMessage("[" + ChatColor.GOLD + "ModUtils" + ChatColor.WHITE + "] Informations sur les CPS du joueur : \n"
+ "- Nom du joueur en analyse: " + ChatColor.AQUA + target.getName() + ChatColor.WHITE + "\n"
+ "- UUID du joueur en analyse: " + ChatColor.AQUA + target.getUniqueId() + ChatColor.WHITE + "\n"
+ "Veuillez patienter pendant l'analyse de " + ChatColor.RED + target.getUniqueId() + ChatColor.WHITE + "."
);
// Enable counter + start heck
config.set("cps." + target.getUniqueId() + ".enabled", true);
config.set("cps." + target.getUniqueId() + ".counter", 0);
plugin.saveConfig();
// Timer
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
i ++;
if (i == 3) {
this.cancel();
}
player.sendMessage("COUNTER TIMER : " + i);
player.sendMessage("COUNTER CPS : " + config.getInt("cps." + target.getUniqueId() + ".counter"));
}
}.runTaskTimer(plugin, 0L, 20L);
// Disable counter + end check
player.sendMessage("End timer");
config.set("cps." + target.getUniqueId() + ".enabled", false);
config.set("cps." + target.getUniqueId() + ".counter", 0);
plugin.saveConfig();
}
Why "End timer" started before the end of the runnable?
Well reflection doesn't have to be maintained if I just get Registry.CLASS_NAME via reflection.
I don't know if such an if-else if-cascade for checking all registries will be faster than reflection though.
Cause your delay is set to 0.
Add however much you need.
20 ticks = 1 second.
Yeah I know.
Did not fix my problem. https://gyazo.com/d8d63c901119a9f6f6178832cd9103b3
The delay is before start running...
@kind hatch
I'd just get a Map<String,Registry> with reflection on startup, then you don't have to worry about speed
that's actually smart. I'll do that
It will be a Map<Class<?>, Registry> but besides that it's a perfect idea
Oh, I thought you had two runnables. I’m on mobile so it’s hard to read your code atm.
private final Map<String,Registry<?>> registriesByName = new HashMap<>();
@Override
public void onEnable() {
for(Field field : Registry.class.getFields())
if(field.getType().equals(Registry.class)) {
try {
String name = field.getName();
Registry<?> registry = (Registry<?>) field.get(null);
registriesByName.put(name,registry);
} catch (ReflectiveOperationException ignored) {
}
}
sth like that is what I'd do
Oh right I can't get the classes since they are erased at runtime. It actually has to be a String (unless I do the Class.forName() at startup aswell)
But that's a pretty neat idea. I'll adapt that
lmao
i mean why not lol
actually a fair point
would save me from building something myself
And enable a dynamic way of obtaining all registries
There is an event for players when there is a fight?
wdym with "when there is a fight"?
do you consider it to be a fight when a player meelee attacks another player once with bare hands?
and if yes, how long?
For example when they are fighting with swords or hands.
When a player do damage on a other player.
The EntityDamageEvent won't suffice unless you don't wanna know who attacked. The EntityDamageByEntityEvent does have both.
Keep in mind that the Damager can be a Projectile in which case you wanna check for the Shooter
You’d want to check regardless because the damager could be another entity.
Hmm I had a plugin which used that, I should probably go back to it and add a few line to check for arrows and then the shooter
Registries are actually keyed so it's something I've considered
The thing stopping me currently has been custom Bukkit registries
But then where will we store the registry registry
In a registry, obviously!
It’s registries all the way down
What event is fired when the player clicks on a recipe book to put items into the grid?
The client sends a packet when placing the items for a recipe
So there has to be some sort of event for it
I guess you could check the type in the ClickEvent https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/inventory/InventoryType.SlotType.html
SlotType doesn't seem to cover the recipe book though
Im uncreative anyone got a easy way to make cool looking guis
i asked chat gpt but hes dumb
man cant even count
i told it to change the 7th bit and it changed the 5th
chatgpt on troll mode 
i know how to code guis its just im uncreative and they dont look cool when i try it xd
for chestsort I just made an extremely boring GUI but it's 100% customziable sooo not my job anymore to make it good looking
i mean thats also a way x)
If possible I like gui designs to be as declarative as possible
Hey @tender shard . I seen you I would not say sick but lets say my brother had that issue in the past and I know how you feel. Continuous going to the hospital every month
I still need to figure out how to make a gui for selecting RGB values
That usually goes well since you get a good design for parent child behavior then inferred
That isn’t horrible to use
Anxiety and depression with that does not mix well
Messing with RGB, you need this https://www.webfx.com/web-design/color-picker/ . You can use this for anything where RGB is required like CSSbody{ color:rgb(255,0,0); }Which colors the text to red. Or you can use #FF0000 (Hex Value) and still be the same color. As a note, its not just CSS where you use RGB
Okay but that doesn’t have anything to do with making a GUI for selection RGB colors
We can use RGB on bukkit plugins?
Yes, since 1.16 iirc
Show a example please because I don't know if this is true
Spoonfeed a newbie for a day and they'll come back with more questions. Teach them to find their own answers and you'll both be better off: you won't get stuck answering the easy questions and they'll be much more productive than before.
Anyway I want to make an rgb selector for some particles
Sure I could have people just put the hex code in chat but that isn’t very end user friendly
Player target = Bukkit.getPlayer(args[0]); how can i get the args and the uuid at the same time? tag me
Why is Bukkit#broadcastMessage deprecated? What should I use instead?
maybe you're using paper api or something
ye im using paper
understandable, ty
Thought it was a bukkit thing!
no worries
making an rgb selector sounds like fun
but ig the hardest part would be the actual ui, like how do you make it intuitive to use
what do you mean at the same time
I see, I think I remember seeing something like that. So that is what you want to do?
Yeah that’s the issue
now i getplayer but i want getUUID but then i dont work how can i get uuid?
?learnjava
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.
probably
like you can us getUniqueId() on your player to get its id
but idk what you mean by at the same time
yeah i did not mean to type at the same time but i need uuid instead of player
okay, then do what I suggested
the one bad thing about the discord is that it doesn't filter out beginners as well
like when I was a beginner I never wanted to post on the forums because that was a lot of work so I would just google
but discord its so easy to ask dumb questions that I do it constantly all the time
How do I integer?
Sorry, but this is objectively wrong. Use BigInteger instead.
actually, you need to buy my premium resource API GiantInteger
also known as Gi-Int
I don't get it
well i guess you dont think big enough
Am I correct in thinking Spigot's implementation of sqlite-jdbc is vulnerable to this? Looks like Spigot is on sqlite-jdbc 3.41.0.0 which is in the range of affected versions. https://github.com/xerial/sqlite-jdbc/security/advisories/GHSA-6phf-6h5g-97j2
Then yeah it is affected
Is there a way to cancel firespreding in a specific area that i have set?
iirc our version of snakeyaml may also have some vulnerabilities
Mayhaps it's time to bump things
Listen to the BlockSpreadEvent check if it's fire and in your area
okay thx
Hmm
Attacker would need access to the URL used in whatever plugin is using SQLite on that server.
True, but that situation could exist. This is a random example, but think a person helping an admin configure a plugin. Admin copies the config over with malicious SQLite URI and bam
Well that admin could probably just install a malicious plugin
or if they have access to the config the credentials are probably there
yep, any user who has root server access can exploit it.
I'm not saying it's super likely or that the admin in question wouldn't be stupid for trusting it. Just that it's a possible situation that could be easily fixed by updating a dependency
not easily as it would break any plugins using teh current SQLite dependency
I see
I forget off the top of my head but I remember it breaking iConomy
looking at the fix, it seems like they would already need to have the malicious code on the server too
This is SQLite not mysql
I haven't looked into much of the details but if it's an RCE couldn't they just wget a malicious script or curl some malicious server with sensitive info to offload it?
I remember looking at it a while ago and reverting an version increase as it wasn;t much of an exploit.
Doesn't look like it to me
Looks like all it allows is a carefully controlled URL to load a specific database file from the server's temp directory
I assume that allows code execution somehow, but still relies on getting that file into the server's temp dir
Is the SnakeYaml update also breaking?
Honestly I don't think this sqlite change is breaking
Ah gotcha.
It was probably not this specific fix, but a change to protocol in one of the newer versions
The snakeyaml issue is different still, and also quite far overstated (just a default option allows loading arbitrary classes, which are already present on the server)
I remember it bitched about the connection method and tells you to change to something else. I forget the details though
That was MySQL not sqlite I think
Still if the snakeyaml update doesn't break anything then I imagine it's worth it
one sec I can go over commits and see
It does, that's why it was foreshadows in 1.19
Ah
The Spigot sqlite is already very recent
Me personally i would simply just
if (hasRCEExploit) {
dont();
}
hMod for MC 1.20 when?
F
https://paste.md-5.net/famufogime.cpp is anyone else doing configs like this, or just hardcoding the key names everywhere?
Or rather create a class that returns the values directly, like this?
public class MainConfig {
private final Drop2Inventory plugin;
public MainConfig(Drop2Inventory plugin) {
this.plugin = plugin;
}
public boolean getEnabledByDefault() {
return plugin.getConfig().getBoolean("enabled-by-default");
}
// etc
}
or maybe even another way?
I somehow do it differently in every plugin lol
Enums are love
I would probably just depend on FileConfiguration or an anti derivative type instead of ur main plugin type @tender shard
Enums are life
But else that’s how you usually define rich configuration objects
or maybe like this, caching the values
public class MainConfig {
private final AnotherPlugin plugin;
private final boolean enabledByDefault;
public MainConfig(AnotherPlugin plugin) {
this.plugin = plugin;
this.enabledByDefault = plugin.getConfig().getBoolean("enabled-by-default");
}
public boolean getEnabledByDefault() {
return enabledByDefault;
}
// etc
}
enum as for config ?
yeah I do that in many plugins too
Unnecessary
It makes the class slightly more reusable
I think so too
I just wondered how other people usually do it
I know a lot of plugins like to do straight raw object mapping
because I've see so many times where people call plugin.getConfig().get("someKey") in 20 different places and I wonder why
that’s bad
like, they hardcode "someKey" everywhere instead of doing it once, and I always wondered why
Thats leaky abstraction v
Give me one sec
Its really bad and give rise to code symptoms
i saw code where every time someone called getKey it loaded the same json file, man called it 14 times in startup 💀
Its a never do
wow
that's almost as bad as synced update checking
Did someone say raw object mapping
im still wondering why people use that crap
Yes
That’s how I do it professionally probably
This is acceptable
A weird constructor and some stuff but else nice
Any feedback is good feedback
Myea well, I think alex wanted a more strongly typed config class definition
I’ve got that wacky reflection going on
so he does not have to fill in keys as string every time
Is that not what ive done ayo? :L
If you just don’t look at the reflection code then it’s fine :D
interface Configuration {
boolean enableBypassHacks();
String mySqlPassword();
}
Such that the members match the typed config format Ig?
@tender shard no?
(I mean obv u dont need an interface)
in plugins with more than one config I just extend this https://github.com/JEFF-Media-GbR/JeffLib/blob/master/core/src/main/java/com/jeff_media/jefflib/data/Config.java
and then do it like the first code example I sent, e.g.
public class MainConfig extends Config {
public MainConfig() {
super("config.yml");
}
public boolean isEnabledByDefault() {
return getBoolean("enabled-by-default");
}
public int getMinY() {
return getInt("min-y");
}
// etc
}
Looks fine
Did u have a look at my one
what was that config api again?
Thatc
Or class
?
mfnalex
is it a spigot page?
Its a bit of an enterprise engineering but ye
no
Im trying to figure out if the way ive done it with the Enums and a manager isnt a good solution to the problem
alr than thas it
yeah but I never use configurationsections
I always have everything as top-level-keys
what are you trying to do now?
otherwise people fuck up indents and then I have to tell them to add a space in line 976 every second day
not yet
Make a gui to change it in game :p
Im surprised noone has made some sort of self-corrector for that shit (not looked too deep into YMLS)
I mean the solution works, but realistically if you have a configuration layer in ur code architecture you want its interface to other modules completely separate from any type of config loading logic, config sink/source logic and config pathing logic. Which is why sth like this is ideal. @livid dove
that depends on what you mean with that. what does it do? do you mean it should run a bungeecord server directly? because very little plugins I can imagine, where this would make sense
(It allows for powerful abstraction)
Nothing, was just showing of my approach to config files and how I avoid writing the same string over and over and risking a fuck up
yes
for configs just stay the fuck away from what I made lmao https://github.com/Y2K-Media-Creations/simpleconfigs
this is prob one of the worst impls and makes 0 sense
Alex u might wanna read this also
But out of interest, why?
That way you decouple the loading logic, source sink logic and pathing logic from other modules
So if something regarding the config module implementation needed a change, your other modules would stay unaffected by the change
spigot uses plugin.yml. Bungee supports plugin.yml IF it doesn;t find a bungee.yml
ah okay. In that case, you'd have two main classes, one extends Bungee's plugin, and one extending spigot's JavaPlugin.
then yo uhave a plugin.yml for spigot and a bungee.yml for bungee
also ideally you'd have an interface layer thats implemented by both and share as much code as possible
yeah that's what I would have written next
oh wait thats not it
Let’s say you use plugin.getConfig().getInt("blobIsDodoDinosaurSpigot”) in ur commands, listeners etc
in the data package
ty
What if you need to change the config object? Or change the path? Or something else?
That’d imply having to find every class that uses the plugin.getConf… and change it manually
painful, and if you work with multiple jars, even more painful
the abstraction thing I said, but otherwise no
I'd recommend using a multi-module project
bungee module
spigot module
api module / core module
Wait surely with the Enum that solves that problem. As everything is sorted manager side right?
If I change how it gets those values, that method wills till go grab those values. If I change how my plugin grabs stuff, my plugin will still go grab that stuff.
The whole point of the enums is I could swap those strings out for anything.
Yeah your way is fine as said
The key for handling configs is all the annotations
I think the issue with using an enum is type awareness
yeah and then you have to ofc also write code for both. I would use three maven modules
- core (handles loading config, etc, has an interface for e.g. "announce")
- bukkit (handles spigot stuff, e.g. main class, and implements the interface by using Bukkit.broadcastMessage)
- bungee (same as bukkit for bungee)
Since enums don’t allow generic type parameters
then you shade those all into one .jar and done
no
entire separate modules
otherwise you'll have dependency issues
The enum in this case is designed to go grab the value.
I.e. there will always be a "getValueAdress".
The beauty of the types of my values is that each value type has its own method. So there is no chance of grabbing the wrong type etc. Hell in future I could set the manager up generically and have it sanity check the type its grabbed before sending it back to the user
https://github.com/Y2K-Media-Creations/Raven/ here is two multi-module examples one in gradle on in maven
https://github.com/JEFF-Media-GbR/JeffLib
yes but each value type is hardcoded
like if u wanted to add a method to get org.bukkit.entity.Player for instance
that'd have to be hard coded
From a config?
yes
as an example
more appropriately u might have the class MySqlCredentials, or ItemStack or sth
the amount of classes is a spectrum, continuum yk
With the greatest gosh giddigy garn respect. Why in the great jumping jesus on a pogo stick would you use configuration files for anything other than just your base values....
Im not gonna be storing players in a config file. My config files are not hotels damnit!
xD
I mean why would skip deserialization of complex types with only base values
that's not the point tho
its not uncommon to have config types of lets say List, Collection Set etc
Now that is fair but still... I dunno... it seems really odd to be storing that stuff in a config.
Or at least in my mind, configs are supposed to be user side friendly. Its what your joe schmo down the street is used to right?
So adding all the extra gubbins in
it has nothing to do with user friendliness
like its just that u decide to make it simple for u
I do not follow
not really any good oens I know of
would u favor
ComplexType type = new ComplexType(config.getString(Key.KEY_1), config.getInt(Key.KEY_2),...,config.getString(Key.KEY_N))
or just
ComplexType type = config.get(Key.KEY_T);
(Key.KEY_T is not an enum constant)
I mean I can already say I'd prefer the latter
i though BlockBreakEvent had like an getAffectedBlocks method to get a block like a door if it was broken by a block
Ngl this is where I start to disagree. I think having the enum constants in there is a great idea purely for the reason i can compartmentalise my various settings more easily.
I think there is benefit to be had, perhaps in even a mix of the 2 options. But I feel uncomfterble having to continoually rely i havent screwed up my file types in the config, not finding out till i try testing the damn thing xD
u do u
I prefer
Id be interested to try a mix of the 2
@ConfigEntry("enabled")
@Comment("Enable/disable this spell part. Disabled parts cannot be used in spells.")
private boolean enabled = true;
looks usable but a compromise in respect to design
for instance this is how LP does it
https://github.com/LuckPerms/LuckPerms/blob/master/common/src/main/java/me/lucko/luckperms/common/config/ConfigKeys.java
https://github.com/LuckPerms/LuckPerms/blob/master/common/src/main/java/me/lucko/luckperms/common/config/LuckPermsConfiguration.java
https://github.com/LuckPerms/LuckPerms/blob/84bd2ee52abbed9624e72435c37fe6fcc3439a8d/bukkit/src/main/java/me/lucko/luckperms/bukkit/listeners/BukkitConnectionListener.java
now this is written by a real software engineer and is a bit enterprisy
but that's very nice to work with
They lost me at 400+ lines in a single class for something being used for configuration settings
well it is abstraction layers and just a lot of thought put into design
whilst it does compromise usability a bit
I dunno man. Im looking at this and all I think is "jesus this could of been turned into an ENUM or literally anything else.
Break down each section of the config into different classes, be able to be more easily compartmentalised / envisioned by devs working on it
Im an aerospace engineering lecturer irl and I have "Raz's Rule" (Real name obvs)
The rule? "Human beings will screw up at least 20% of the time"
I see a 740 line class and I just see "Accident waiting to happen"
I mean u have test driven development
which is what companies enforce
sometimes just AGILE in general
I get that. I really do. But it doesnt change the fact 700 lines in one class is bad form imo
Its a class... for configuration settings
yeah u can spread the key constants out into different classes sure
its just a compromise of maintainability to centralization
Eh The way I see it I could slap a new section of my config today, and all it requires is a new enum.
Note the utter lack of actual values in the class though
here u centralize around ur plugin main
Right? So whats the issue?
When i heard "Cetralization" i figured u meant more like what LP did
Where they slapped everything and the kitchen sink into one 700 line monster of a class
Values, methods etc
na not rly
lines is irrelevant to some extent
but obv 3000 lines does imply bad design choice
What would you suppose the "new line to new addition" ratio of that class from LP is?
Thats where i'm getting seriously off vibes with LP's example
which class ?
keys
its in one class for several reasons
I mean if i am completely blunt?
Its almost like, in my humble little dumb dumb brain, looks to me as they have just essentially accidentally rewrote the configuration file again in that class
E.g: You mentioned the more complex cases and values right?
yes but there are other benefits to object mapping
tho its more of an enterprise and pro practice
For record, if I needed more complex values in my plugins, i'd add a new method to the config manager ngl.
same retrieval processes
Just... more complex.
na not really
its better than 95% of plugins design wise
I meant LP
-_-
urs is also probably better than most tbf xD
:)
Im half irish so i can get em for copyrights
I mean our team actually does UML diagrams before we code so ur probs not wrong
lmao
There are things im 100% not happy with in landlord
for example, the messages class is a mess
Actually embarassing
You dont or I dont lol
Did u mean u or me?
this1
How so?
first of all I'd use other, more sophisticated component framework clsses
but also mini message lmao
Could you give an example?
nrn but later sure
No why make extra effort?
Strings support all of that
And strings totally tell you when youve got it wrong right?
Right?
Unless ive missed a trick, if you make a multi color string for a message raw... the moment u'll find out if its worked proper is in the test 😉
Or you just... know what you are doing?
Another thing I teach my students literally all the time.
"protect your stupid"
All my messages are just pulled from a file anyway
A rocket once blew up and millions of dollars were wasted because nasa tried manually converting from metric to imperial.
"Just know what ur doing" is realllll silly
Its not for a simple and unimportant thing like multicolored messages lol
For my own sanity, show me an example of a multicolored, custom colored (hex code) string
Cause im always happy to see other perspectives
Someone give me an example rq
what are you a teacher in if I may ask?
Aerospace Engineering
ah
I assume it does not involve that much design practices etc? rather just programming related to aerospace stuff?
Im self taught. Started around 6 months ago
*for coding side
I did not self teach myself aerospace engineering xD
Let me rephrase:
I have a first class masters in aerospace (honrs babbyyyy) and ive self taught myself java in the last 6 months.
ah alr
`getLogger().info("======================================");
getLogger().info(translationManager.getTranslation("plugin.enabled"));
List<String> startupMessages = translationManager.getBulkTranslation("plugin.startupMessages");
for (String message : startupMessages) {
getLogger().info(message);
}
getLogger().info("Version: " + getDescription().getVersion());
getLogger().info("Author: " + getDescription().getAuthors().get(0));
getLogger().info("======================================");
`
This look good?
it makes sense the way you think about object oriented design and java is a bit intermediate/beginner like, but its alright, ur code is quite good given the time span
nice :)
I apply myself haha
I have been coding for 6 years and my code is still the biggest garbage ever ;)
The thing is
Indeed
I do not have that low amount of total projects written
Easiest way to learn anything imo? Do the stupid shit intentionally
to see how dumb it is
But yeah... idk what im missing on
then do it the proper way
From what we've already discussed. I'd bet bottom dollar the most important thing I tell my students
"Context is Key"
Just be careful not to develop bad habits along the way. Being self taught, I definitely fought my bad habits for a long time
AKA: .
Its why i make my repos public :L
Lol yes. Trial by fire
Nasa blew up 30 million dolar engines to fix a problem by Randomly changing the shape of holes in a plate with no maths involved to fix a problem once
Idk if its a bad habit if its the the thing I like most
trial by fire is how we got here
the easiest counter measure is open mindness
I like not havin to worry about naming convention :L
***An open mind is like a fortress with it gates unbarred and unguarded"
i disagree
"Context is key"
*its a joke
xD
:>
Warhammer 40,000 Dawn Of War Unit Quote belonging to the Space Marine Librarian.
"An open mind is like a fortress with its gates unbarred and unguarded."
Naming conventions are only useful if you think you'll forget what a varible is for, working in a profession setting (jobs) or sharing your work to other people for help, or just sharing with the intent of people remixing
refer back to my "you screw up 20% of the time" rule
Lol
Why use descriptive names when random letters do trick
Exactly
I mean, when i post something here
i cntr f and replace
Manual obfuscation
Put all ur code onto one line. That way you know where everything is
i mean the rule is the name should be proportional to the scope
one line?
yeah, only if other people will see it i think
Why?
My methods be like: public void a0Lan4fB1sI()
Had a stroke reading that
Legit btw always happy to be roasted habits wise. Also reading material is always nice
the reason naming conventions exist is for clear communication of your code
otherwise it has no purpise if you dont want to share
Einstein once got set back 6 months as he short handed notes in one of his late night scribbles
Indentation is a good practice, but there are things that automaticall format
Until you come back to your code 6 months later and don’t understand anything
Dont be like einstein
It wasnt anything worth publishing probably
Well, the big difference between color codes and naming conventions is that wrong naming conventions confuse other people and make problems for them, but color codes don't
“What’s this variable for and why is it called boobs”
😉
Fr though, I have a ton of small-ish plugins I maintain and any time I need to fix something I have to borderline reverse engineer it to figure it out. Poor naming conventions would make it 10x harder
cries in land dev
Did u guys ever spot btw how the crops modifier in spigot was broken fro like 4 years?
I understand my own thought processes, maybe other people wont, for them they should have proper naming conventions, actually even then, a bunch of these rules for naming is again, mainly for communication, you could have clear and describtive varibles without followng these conventions unless your of course sharing
public void boobs(). Omg imma call my next method I write like this, whatever it is gonna be
You giving me hella ozymandias vibes with that first half ngl
I fucking hope so after I spent half a month in the tickets trying to explain the problem
lol
it was a week into me learning java i spotted it. It was the moment I went "jesus christ if I put effort in I'ma gonna fuckin thrive here"
Imagine if md_5 or someone else in spigot did this and some day people in discord be like: "Bro why is boobs() showing up to take 50% of my tick-time in this timings report???", "uhm... its complicated!"
I dont know what that is lol
This started as a kinetic text experiment based on Bryan Cranston's reading of Percy Shelly's Ozymandias, for the season 5 Breaking Bad teaser trailer.
Needless to say things escalated from there. Before long I was messing with Blender's Cycles engine more than I have before, as well as cloth simulation, low poly modelling, dynamics & forces, a...
well mainly but there are other reasons also
Consistancy, ease of reading yourself, increasing complexity management (contextutally), subconcious context, reduction in errors
To name a few personal benefits
That’s a great idea
I’m on it
If your going to bring up rememberance, then, yeah if you have trouble remembering things then use descriptive names, I mean for example, js has crazy naming conventions, like, for (let i, Array.lenght, i++)
apprently for loops your supposed to have only i or j as varibles, which is probably going to be cared about in a professional setting
Hide that in your next PR into spigot ;)
Psssht md5 you won't read this message
lmao
i, j or k is the right choice even in professionalism
md_5 checking the PR: "hmmm this is FINE, im in"
this again
It also may be an issue that I gotta go to school in 5 hours
I hope you can forgive this single intrusion. But I just got Chat-GPT to write something as a funny and it honest to god SLAPPED on the first try lmao.
I met a coder from an antique startup
Who said: "Two vast and trunkless classes of code
Stand in the workspace . . . near them, on the desktop,
Half sunk, a shattered comment lies, whose symbols,
And function calls, and unreadable syntax,
Tell that its sculptor well those passions read
Which yet survive, stamped on these lifeless things,
The hand that mocked them and the heart that fed:
And on the commit message, these words appear:
My name is Coderzmandias, King of Kings;
Look on my Works, ye Mighty, and despair!
Nothing beside remains. Round the decay
Of that colossal wreck, boundless and bare
The lone and level sands stretch far away."
Revising, I read through his cryptic verse,
Straining to glean some logic from the terse.
For his creations, so complex and vast,
Yet to others, they're relics of the past.
Of these lines of code, to his boast's compare,
Only confusion and frustration bear.
His 'Works', once mighty, in obscurity lay,
Engulfed by the sands of time, in endless array.
but you cant like, forget what the purpose of i, j or k is in a loop. nor can you forget anything else like l, b, or s being used
na
like for instance
catch(Exception e)
that scope is small
thus the variable name can be short
How small are we talking
Thats a rule that I can agree with, small scopes get small names
What about a zero width space
good because its unspoken but official in enterprise
im just saying, you need to focus more on comments than naming. Comments are literally the best way to communicate what your doing
na