#development
1 messages ยท Page 116 of 1
Is there an admin online to re-verify my plugin, Glare disabled it at my request due to it having a breaking bug and ive got round to update it and it is all sorted now? Looks like trying to pull it ingame downloads an old version which is odd, not sure if thats something you can fix aswell, but the 1.4.2 release on gh/eCloud work fine from all my testing
https://api.extendedclip.com/expansions/floodgate/
I gotchu
Showing as offline i see, thanks ๐
You can always DM me. I usually am around.
Verified now. Should show up in the next hour or so in-game.
Excellent thanks ๐ also noticed the date ingame was showing as published 1.3 18 days ago which is very wrong, not sure why that was
Not even sure how it's showing in-game to download from since it wasn't verified unless you enabled the config setting in PlaceholderAPI.
I did
Was 18 days ago when I unverified it?
ah maybe
Might be an internal backend bug I need to look at, but it's not game breaking at least.
looks like it
Looks like it's already showing in-game but the cache will overturn and show everywhere over the next hour or so.
Feel free to DM me if you need anything else
how can i send data via proxiedplayer to server?
ServerInfo#sendData sends the data via first element of ProxyServer.getInstance().getPlayers(), not the specified player
ProxiedPlayer#sendData sends the data to player's client, not to the server
i am just going to specify the player in the data
i guess there is no other way
Yeah, I was thinking of something like that, would like to avoid making a server for it tho. Would have preferred dc or smth else. And as for modifying the resource code, that is always something I have to worry about, can't really do much about that.
if you absolutely can't host your own server then a (very crude) solution might be to have a public registry of activated plugin key hashes - maybe on github?
your plugin can accept a plaintext user key from the config, calculate its hash and compare it to the hashes on the github page
it doesn't scale too well but ๐คทโโ๏ธ
nothing jumps out at me as super dangerous about this, but that doesn't mean there are no hidden flaws
doing it this way also means that you would not be able to use discord account ids as the plugin key - instead consider issuing a (very long, like in the kb) base 64 encoded key to each buyer
this actually seems like a pretty cool project idea, so i'll steal it from myself and see if i can make a library for it
also someone just mentioned this but you can host a small server for free forever through oracle, so don't give up on your hope of having a verification server
#off-topic message
note that oracle might just terminate it in like a year ๐ฅฒ
happened to a lot of ppl here
oh oof
do they terminate their 'forever free' tier? they do mention they have stuff that's free for 12 months, that would make sense to terminate after a year
big oof
what abt mvn central?
I have a locally hosted server already, so adding a sql or smth should not be too hard. Just wanted to avoid it since I don't want do it unless it is necessary, guess I will do it tho. Github idea seems cool, but feels better to store the information locally. Thanks!
sure thing, good luck with your endeavor ๐
Thank you, I'll probably need it lmao
Making a db isn't hard, using it is (never used one in a plugin b4)
wait
you're not directly connecting to a database you host through your public plugin right
right???
DRM ๐คฎ
droopy roopy monke
I didn't really read much above, but I hope you have a really good reason for this DRM, and even if you do, that's not enough
all DRM does is harm people who genuinely use your service
i dont think he has anything that would qualify as such for you
but i think making a good drm is an interesting technical challenge
so ๐คทโโ๏ธ
well if you look at some of his constraints
he wants to avoid hosting server if possible
wait what lol
so you need to do something like what i described and rely on github or some other public point of reference
well yeah that does actually sound interesting from a cryptography and secret-keeping kind of perspective
right??
still wouldn't recommend actually implementing, especially for a minecraft plugin
yeah seems kind of pointless
actually i remember seeing an anticheat plugin a while ago that had some drm
they had their own server that used ML to decide if players on whichever servers were cheating in real time
since that was a subscription based thing drm sort of makes sense there
wow, that sounds overkill
i mean, I wouldn't consider that DRM if you're just paying to use the server
yea lol
doesn't matter to the person running that server if you distribute copies of their clientside plugin
Hey, I'm trying to make an setspawn and spawn commands but I'm struggling with the config part. Maybe can someone help me?
SetSpawn CMD
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(sender instanceof Player p){
if(p.hasPermission(Config.getString("setspawn-perm"))){
plugin.getConfig().set("Spawn.world", p.getLocation().getWorld().getName());
plugin.getConfig().set("Spawn.x", p.getLocation().getX());
plugin.getConfig().set("Spawn.y", p.getLocation().getY());
plugin.getConfig().set("Spawn.z", p.getLocation().getZ());
plugin.getConfig().set("Spawn.yaw", p.getLocation().getYaw());
plugin.getConfig().set("Spawn.pitch", p.getLocation().getPitch());
p.sendMessage(Colors.color(Config.getString("setspawn-msg")));
Sounds.success(p);
}else{
Config.noPermission(p);
}
}
return true;
}
Spawn CMD
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(sender instanceof Player p){
if(p.hasPermission(Config.getString("spawn-perm"))){
if(!plugin.getConfig().contains("Spawn",false)){
p.sendMessage(Colors.color("spawnnotset-msg"));
Sounds.fail(p);
}else{
World world = Bukkit.getWorld(Config.getString("Spawn.world"));
double x = Config.getDouble("Spawn.x");
double y = Config.getDouble("Spawn.y");
double z = Config.getDouble("Spawn.z");
Float yaw = Config.getFloat("Spawn.yaw");
Float pitch = Config.getFloat("Spawn.pitch");
Location loc = new Location(world,x,y,z,yaw,pitch);
System.out.println(loc);
p.teleport(loc);
p.sendMessage(Colors.color(Config.getString("spawnteleported-msg")));
Sounds.success(p);
}
}else{
Config.noPermission(p);
}
}
return true;
}
It's not overwriting the config file and If you guys know a way to check if the List is empty that'll help
are you calling plugin.saveConfig();
oh
well, I wouldn't recommend using YAML for data storage like this period, this sounds like a job for JSON and serialization
but yeah what Ivan said ^
I don't know how to use JSON
(also spigot has a builtin Location serializer)
It's easier to use than YAML lol
like I can store the location in the server?
you also seem to be saving each player's spawn data to the same spot in the config
without writing it in a file?
No
like you dont differentiate based on player, so you end up with a shared field which is probably not what you want
He means that the Spigot API has a way to serialize locations easily
Here, check out this guide on JSON https://www.spigotmc.org/threads/json-configuration-files.212794/
what do you mean?
sets the spawn for everyone
you set the x,y,z,etc values in your config to that of bobs new spawn
wait
ah for some reason i was totally thinking of this as homes
ignore me
lmao
to be fair, I kinda was too
The code is messy?
it's a little messy but also i just cant read
Moderately, and I just presumed you were looking for more
the method of storage matters less when it's a single location, I suppose
I don't know why it's so complicated to make an setspawn command
you could break things up a little bit to make it more readable
make setSpawn(...) and getSpawn() methods that interact with the yaml config so the command methods aren't clogged up
no - ```java
config.set(location);
config.getLocation("path")
wdym?
#---------------------------------------------------------------------
# MESSAGES
#---------------------------------------------------------------------
no-permission: "&cSorry, &7You don't have the right permission to execute this command."
setspawn-msg: "&a&lSUCCESS! &7You've set the spawn successfully!"
spawnnotset-msg: "&c&lERROR! &7There is no spawn set in the server."
spawnteleported-msg: "&a&lSUCCESS! &7You've been teleported to spawn!"
join-format: "&8[&a+&8] &a%player%"
firstjoin-format: "&8[&a+&8] &a%player% Has joined for the first time!"
leave-format: "&8[&c-&8] &c%player%"
#---------------------------------------------------------------------
# PERMISSIONS
#---------------------------------------------------------------------
setspawn-perm: MegaWallsFFA.admin.setspawn
spawn-perm: MegaWallsFFA.spawn
#---------------------------------------------------------------------
# HELP MESSAGE
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# LOCATIONS
#---------------------------------------------------------------------
Spawn:
world:
x:
y:
z:
yaw:
pitch:
#---------------------------------------------------------------------
# LOGS SETTINGS
#---------------------------------------------------------------------
joinleft-log: true # Enable/Disable Messages Logging to discord with webhook
joinleft-url: "" # The Channel Webhook URL
That's my original file
ah you're wondering why the comments get removed
#
# SETTINGS
joinleft: true
firstjoin: true
joinleft-actionbar: true
joinleft-title: true
joinleft-hover: true
no-permission: '&cSorry, &7You don''t have the right permission to execute this command.'
setspawn-msg: '&a&lSUCCESS! &7You''ve set the spawn successfully!'
spawnnotset-msg: '&c&lERROR! &7There is no spawn set in the server.'
spawnteleported-msg: '&a&lSUCCESS! &7You''ve been teleported to spawn!'
join-format: '&8[&a+&8] &a%player%'
firstjoin-format: '&8[&a+&8] &a%player% Has joined for the first time!'
leave-format: '&8[&c-&8] &c%player%'
setspawn-perm: MegaWallsFFA.admin.setspawn
spawn-perm: MegaWallsFFA.spawn
Spawn:
world: world
x: -2569.0295060817352
y: 54.5
z: 744.5529914894588
yaw: -89.882774
pitch: 6.8998375
joinleft-log: true
joinleft-url: ''
and that's what happened
that's YAML baby 
that's just something snakeyaml does, i don't like it either but i haven't seen any easy ways to get around it
that's spigot yml*
or u can save in separate yml file
^
i saw someone do a lil trick where they saved the comments as values in the yaml file
so that they don't get erased
like
spawn-perm-comment: "the permission to use /spawn"
spawn-perm: "perm.perm"
hate that
it's big brain
real comments are definitely better but the ingenuity is to be respected
spawn perm, or, to abbreviate, sperm
haha.... ha... very good humor...........
Yes
I am currently getting an error for UnknownFormatConversionException when trying to use the setFormat method within the AsyncPlayerChatEvent. I've used a debug logger message and nothing looks out of the ordinary so I am not exactly sure why I would be receiving the error. I know about String.Format being needed, and it's what I have been following, but for some reason it is still not working.
The Error: https://paste.md-5.net/aropimaxoj.bash
The Code: https://paste.md-5.net/icokofivak.js
Debug Message: [14:59:36] [Async Chat Thread - #0/INFO]: [Stylizer] %s >> %s
Chat Format From Config: "%displayname% #14abc9>> #6b6b6b%message%"
I have tried using %1$s and %2$s as well as the generic %s but can't seem to find what is actually using the error. Any help would be appreciated as this error is annoying me
hey, uh, how does one parse player skull textures?
I'm using this web for textures/skins
https://minecraft-heads.com/custom-heads/miscellaneous/24497-objective
and I'm trying to do something like DeluxeMenus (iirc) does
where the material goes something as follows basehead-[some-uuid]
some-uuid is actually a json encoded to base64
{textures:{SKIN:{url:"https://textures.minecraft.net/texture/...."}}}
more complicated than I thought
so basically it's pulling data from the minecraft profiles, getting the texture and applying it to the skull?
yea, I guess
๐
I'll ofc use a proxy, why?
define proxy
Does anyone have a custom enchant skript?
you should not be connecting to your private database with your public plugin since people can dig around and find your database credentials
yeah
?
thats the worst thing you could possibly do
and then they can do all sorts of evil stuff
make them use their own
not about you spexz dont worry
ok
if you're still planning on hosting your verification server, you should only be exposing the API server and keeping the database itself hidden
yes
rest apis are easy to make
especially if you go with enterprise systems like Micronaut or Spring
spring is a very popular choice ^
java.lang.IllegalStateException: Asynchronous getNearbyEntities!
Me getting this error while doing this List<Entity> nearbyEntities = (List<Entity>) EntityArea.getWorld().getNearbyEntities(EntityArea, 15, 15, 15); HashMap<String, Double> rangeplayers = new HashMap<>(); for (Entity entity : nearbyEntities) { if (entity instanceof Player) { if (entity != player) { Double distance = Double.parseDouble(String.format("%.2f", player.getLocation().distance(entity.getLocation()))); rangeplayers.put(((Player) entity).getUniqueId().toString(), distance); player.sendMessage(entity.getName() + " is " + distance + " blokken van je verweg"); } } }
youre running it async
it literally says it in the error
Cloudflare. I currently have my server network protected by cloudflare and imagine it won't be to bad to add a db to it
why
Under it it will upload it
what
well
under this piece of code
I will send a webrequest to upload the information
if i do that, then theres a big lagspike
everytime i do it
so i think async will fix that
supply a future when you send the information
the entities looping can be on the main thread, but you can send the info async
and just supply whatever information you need to supply
// async code - ExecutorService, runTaskAsynchronously, etc
Bukkit.getScheduler().runTask(plugin, () -> {
Collection<Entity> nearbyEntities = EntityArea.getWorld().getNearbyEntities(EntityArea, 15, 15, 15);
// etc
});
or that
ye
ยฏ_(ใ)_/ยฏ
that doesnt do it async tho
it schedules to the next tick iirc XD
no i mean
he already has it async
so thats how u get it back sync
yea that works too
there isn't any way afaik to get back on the main thread without waiting a tick
the most cloudflare can do is hide your IP address. It won't prevent people from connecting to your sql server if you expose it
if the plugin you are making was only meant to run on your network you would be fine, but since this is a plugin you want to make available to the public, you absolutely cannot directly connect to your own sql server from it
i mean its not just bad security
more like
you are literally giving your plugin the password
since you want to connect to the db
that is bad
Guess I'll have my server look up the entries in the database and respond, not have the plugin connect to the db directly.
thats a much more reasonable thing to do
yes
very
in a perfect world you would make your api server standalone though
so that it wont go down if your server goes down
and so you can scale it independently
or wait maybe you wanted to do that from the start
That seems reasonable. I may have some old server computers, from before my mc network upgrade, to handle it.
i just read server as mc server
What do you mean? Confusion
i thought you meant you would have your minecraft server respond to the api calls
no
My server as in the computer that handles my server network
just make a quick Rest API with lets say Micronaut
you can have your api server on the same machine as your network that part is fine
yeah
but if you have some low powered machine you want to use instead of your beefy mc network machine that might be a better use of resources for you, but thats all up to you and not critical
so i only gotta do the webrequest async?
Hey i get this error: https://www.toptal.com/developers/hastebin/mogokucezo.apache
16.01 16:55:58 [Server] INFO Caused by: java.lang.ArrayIndexOutOfBoundsException: 45
And this is my code:
https://www.toptal.com/developers/hastebin/popajefume.kotlin
Can someone help me?
I do not get what is wrong
How many rows does the inventory have? Are they both of the same size?
Np lol
java counting 
I've done that mistake too much making GUIs lmao
Hahahaha
Hey I'm having an issue where I'm importing WorldGuard just fine but when I go to compile, maven says it cant access one of its classes. It's imported as a repo and depend in my pom. And suggestions?
That explains a lot
Did you add the jar to the modules?
To the project *
use gradle 
No
This is my step ladder. I never knew my real ladder.
Nahhh gradle stinks lol
Do that
/j
bad opinion
Just add the .jar in the project
The only modules I have are the ones maven added from the pom
Can we see ur pom?
yeah
?paste
Paste Services
When asking for help with a config/menu/code issue please use our paste bin:
(we prefer it over pastebin.com)
โข HelpChat Paste - How To Use
I add it here
and that works for me
noo
It does work. But use maven
whyy
https://paste.helpch.at/anakadewem.xml ignore the commented out repos, they're there in case i need to re-add them
youre evolving, just backwards
I use maven
no
Did you do what i said?
Are you using all the correct versions?
Yes I just added the correct version and still nothing
@sharp cove I need to add it w maven
Both
No?
You're not supposed to have to do that
It works, but you shouldn't do it.
okey
I'm not really great with Maven, but it looks fine to me. I honestly have no clue
Can we see the entire error message?
"cannot access com.sk89q.worldguard.WorldGuard"
unfortunately that's all i got
it's not the ide bc i can do alt-enter and import it no problem
But it was a long time ago, don't know what it was
yeah
Am I dumb, or does WG 7.0.7 not exist?
idk, i got it from their website
ok ill try those
That worked, but now i have the same thing for luckperms lol
I'm not using it tho so I'll just take it out
tysm!
actually
I didn't notice u could first
sorry, i have the same issue for another thing
Noice
for ultraprisoncore
cannot access me.lucko.helper.plugin.ExtendedJavaPlugin
i thought it said luckperms but nvm
Nvm, it does exist. Is it stable tho, since it is not on bukkit?
Wait, why are you using Java 8?
Ahh
Well it's a snapshot
That might be why it does not work then?
Oh yeah lmao that is actually the reason
His maven is setting Java to 8
That version of WG only works on 16+
There it is
Hi guys. I seriously need your help. I don't understand how to change a player's nametag prefix/suffix.
With wat? Vault? "Over the head" nametag?
yes over the head nametag
player#setDisplayName
yeah
player#setCustomName iirc
Nop it doesn't work
You set setCustomNameVisible to true?
yeah
Idk then
php-cgi.exe not found: Please ensure that configured PHP Interpreter built as CGI program (--enable-fastcgi was specified)
Help
@pulsar ferry do you know how to?
How would i go forwards coding a plugin that "removes hunger" or gives the player infinite saturation? I'm quite new to Java and minecraft development, and i need this for my server
Anyone faced this issue when using the jlink gradle plugin to get a jfx executable image?
Two versions of module javafx.base found in {Project_Directory}\build\jlinkbase\jlinkjars (javafx-base-16-win.jar and javafx-base-16-mac.jar)
you can make a simple plugin that removes hunger by making an event listener that listens to FoodLevelChangeEvent and cancels it
Yeah i figured that out after some exploring of the different events and then googling them lol. Thanks anyways though :D
๐
@EventHandler
public void onKill(EntityDeathEvent event) {
Entity entity = event.getEntity();
if (entity.getScoreboardTags().contains("pigkid")) {
event.getDrops().add(new ItemStack(Material.BLAZE_ROD));
event.getDrops().add(Main.lavacore());
}
}
I really honestly dont know why this is not working :/ its not adding the drops...
here is the mob:
Player player = (Player) sender;
LivingEntity mob = (LivingEntity)player.getWorld().spawnEntity(player.getLocation(), EntityType.PIGLIN_BRUTE);
PiglinBrute z = (PiglinBrute)mob;
World world = player.getWorld();
z.addScoreboardTag("pigkid");
z.setMaxHealth(1000);
z.setCustomName("ยง6General Pigkid");
z.setHealth(1000);
z.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 100000, 2));
z.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 100000, 2));
z.isAdult();
i think his tags are getting reset but idk
z.addScoreboardTag("piglinos");
entity.getScoreboardTags().contains("pigkid")
oh
no piglinos is completly different but i have a pigkid tag
before i was told it was better to use scoreboard tags so now im using em
hmm
can you add a sysout inside the if (entity.getScoreboardTags().contains("pigkid")) { block, to see if it is being called at all
k
Use https://paste.helpch.at/ for errors, logs and configs. So we don't spam the discord.
Hello, I can't get the placeholder from the plugin DeluxeTags to work.
getting this error.
https://paste.helpch.at/sivipamuse
I use the chat plugin essentials chat.
Can someone help me?
update placeholderapi
- wrong channel, use #general-plugins for plugin support next time ๐
thank you, my problem is resolved.
I use IntelliJ and would like to see what my plugin is doing after I run a command, since it don't seem to do what I think it should. There must be a line that it hangs up on without an error
Just send after every action you do a log message to the console then you see which message is not being sended
none of the log messages got sent to the logs
Then it goes wrong at the start ๐
yes many other things work fine just not the check on island levels
Anyone know why this check might not work when breaking wheat/carrot/potato crops?: BlockBreakEvent
if (event.getBlock().getBlockData() instanceof Ageable) {
```I've used the block import as well
isnt it getState() ? (just saying, didnt use that in a long time)
doesn't work either, but I dont think that works for crops tho
getBlockData should work
if its not returning, then probably not a Ageable
getState().getBlockData() instanceof Ageable? 
Nope, neither - and Wheat/Potatoes/Carrots are ageables tho
make sure you're importing the right Ageable interface
cuz there are two, one for entities and one for block datas
datas 
yep I am import org.bukkit.block.data.Ageable;
in the end it'll be such a stupidly simple solution over which I slammed my head against the desk soooo many times...
I just cant annnyyymoorreee some one please help me out of my misery xD
solved it, thanks tho
Couldnt u just instanceof Crops? Havent done it in a bit
If I mount an entity using packet, does the server recognize that I'm mounting the entity or as the passenger of the entity? Like does Entity#getPassengers will be empty?
It might know that the player is mounted on an entity (I kind of doubt it) but it will have no reference to the entity involved because its only client side.
So the server wouldn't know If the entity has passengers?
Let me explain to you a little bit of what I'm trying to do, basically I want to make teleportation with passengers possible, and I heard that's possible with just NMS so I'm trying to figure it out and all this time I'm using EntityLiving#startRiding, would It make any difference If I'm using PacketPlayOutMount to mount instead using that method?
Hey so Iโm going to create a plug-in that allows players to block people from entering their plot. Iโm thinking of using the towny Api and flinging the players back when they enter. Iโm just not sure how I should have the data stored. Should I just store the plot coords and the list of players blocked in a yml file? Do plots have an id or anything? Thanks
Are you trying to use other plugin API?
No I know how to use an api, Iโm just wondering the best way to store the databse of blocked plots and whoโs blocked in them
So if a player stands in their plot and does /plot block <player> how should I save the plot and the banned player to be used in the future
I'm assuming the API has a Plot object or some kind, maybe you can store that information that is unique to that plot.
I was thinking a yml file like
plot-id:
- player-uuid
Ok thanks
Yeah you should store the owner's uuid, I think it's good.
Since a player can have multiple plots afaik.
Ok, but do you know if a towny townblock has like a unique identifier I can store or what
I don't know
Oh wait
It looks like thereโs plot metadata
The wiki says I can store custom metadata in the townblock
I will look at that
Yea
You have to despawn and respawn the passengers I think, or dismount them and mount them again
I can't detect If player is trying to teleport.
Are the passengers packets?
I'm using the EntityLiving#startRiding method to make the entity ride player.
Oh well if you switch to packets it may work, in a plugin I recently made both the entity and setting passenger was with packets, and despawning and respawning the entity on teleport worked
I can send the GitHub link to the plugin I made so you can see
Are you using ProtocolLib?
Yeah
Well, I'm not. To modify the passengers, should I use reflection?
You can just send regular packets
You donโt really need reflection
You can just make a bunch of interfaces for different versions
And then use one depending on the server version
There is no method to set the passengers sadly, well it has but it requires PacketDataSerializer.
Wdym?
Iโm pretty sure you just send the packet right?
Well, I haven't set the passengers yet, so it's just send nothing basically.
Doesnโt the constructor take the passengers? Or is that not how it works?
That's the player's entity I think.
Oh yeah
One sec
https://wiki.vg/Protocol#Set_Passengers
Is this the same packet?
Iโm not sure why there isnโt an option for passengers in the class you sent
That's the same packet I think.
Maybe you can add fake nms passengers with the same ID to the nms player?
Is there any reason you donโt want to use ProtocolLib?
At first I don't understand how it works, but the plugin is already working on 3 different version, so If I want to switch to ProtocolLib I need to do a lot of changes, that means consume a lot time also.
I guess you might be able to use reflection to manually set the entity IDS in the b[] field
Can you not set data in the PacketDataSerializer class?
Could you actually send that class? Iโm not on my computer right now
Yeah
I hate obfuscation lol
Reflection might be your best bet if you donโt want to switch to ProtocolLib
Alright, I'll read some tutorial how to do Reflection, thanks for your help!
No problem, good luck! If you want to see how I did it with ProtocolLib let me know.
This is what I have right now https://paste.helpch.at/oresinizem.cpp
Looks good
The plugin I made was actually a backpack one lol
Looks like youโre doing the same thing
Idk lol
When you try to teleport does the PlayerTeleportEvent got called?
Yes
Thatโs when I remove the passenger
I totally believe you xd. I've been searching for months but I got nothing.
can anyone please tell me how to make player data system.
like make a method
PlayerData().addKills(player)
PlayerData().addDeaths(player)
and a database with hashmap
learn java
;-;
What's the new thing in paper for this
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
java tool chain 
whats a good representation of coding? Im making a drawing
Code
i ment like a symbol or simeting
Hey what is best practice to save (and load) skyblock worlds if I have a big server. Since I would have multiple servers running where the person can play skyblock but he needs to have the same world on all servers
Lets say I have 3 servers with each 30 spots. I want if I make edits to my skyblock on server one, that server 2 would also have that same exact skyblock when I join that one
When you pick up an item from the inventory, and then PlayerInventory#clear, it doesn't remove that item... so how do I remove that item?
it allows players to bring items from one round to the next :/
Can you give an example please?
Is it just
java {
toolchain {
languageVersion = JavaLanguageVersion.of(16)
}
}
pretty sure they give an example on their github page as well but I think that's right iirc
If you use update() iirc it should help there
Is there a way to check Material of any shulker box color? or should i just check for all the colors? I want to disable opening shulkers, maybe there is another way to do it?
I thought about just Material.SHULKER_BOX, but that is just the default purple one right
I remember it deleting whatever item was on the cursor when used in a click event, which is why I suggested it
also, is there a similar method of doing this for beds?
hmmm
Getting this error when building using shadowJar
> Task :shadowJar FAILED
ex
org.gradle.api.GradleException: Could not add file 'C:\Users\45512\Desktop\JAVA\plugins\build\classes\java\main\net\valdemarf\parkourplugin\commands\Restart.class' to ZIP 'C:\Users\455
12\Desktop\JAVA\plugins\build\libs\ParkourPlugin-1.0-SNAPSHOT-all.jar'.
Never seen it before and can't find a solution on google
This should be correct?
Here's a scan https://scans.gradle.com/s/souf653bi3wwy
Oh wait doesnt this mean invalid JDK version? Unsupported class file major version 60
I think you need a newer version of shadowJar, 7.0.0 probably
Ohhh yeah you're right it has to match the gradle version I use gradle 7.3 and shadowjar 5.3 or smth
Ye
Works now, thx a lot
Ummm so which one is the actual useable plugin?... lol
I'm guessing the top one but yeah
Oh, well, thanks
In that case it doesn't matter they are the same
If you are shading things then it'd be the -all
I'm shading ACF I think
Or well I'm supposed to lol
compileOnly doesn't shade, use implementation
oh.. It just said compile in the guide so I assumed it meant compileOnly
compileOnly means it only needs it at compile time
Oh yeah, and since ACF isn't in the directory at runtime it has to be implemented ig
Fixed, I keep getting this error without anything breaking though https://paste.helpch.at/puhatokuje.bash
It doesn't really do anything as far as I'm aware
Is anyone here good with the Essentials API?
ยป Give the helpers some details
ยป Ask suitable questions
ยป Be polite
ยป Wait
How helpful, it was a yes or no question..
Is anyone here good with the Essentials API? I am trying to use KitClaimEvent to get the kit's items' names, and replace them with the same names except run PlaceholderAPI through the names
If you ask that question no one will answer, if you just explain what the problem is even people that don't know the api might be able to help you
a basic conversation you will have with yourself :kek:
I asked the question
yes I know. I was just meme-ing. I had to
Blitz on its meme trip
yes sir. k. let's get out of here. his question is dissapearing. Mantice might want to ask again so the question is not lost
Yes, does anyone know?
doesn't look like you can update the kits on KitClaimEvent. all you can do is cancel it.
I don't know why they insist on making their API like this or just not adding PlaceholderAPI support, I mean, I saw last night they were planning to in a github post, but that was in 2018
Papi support ๐คฃ ๐คฃ ๐คฃ yeah, good joke
Dont you want a discord module insted? ๐ฅฒ
gaby pr or shut up
Essentials is bad and cmi is not os, so I gotta use it ๐
Yeah but CMI also charges for something that's basically Essentials lol
Definitely don't need all those extra features
cant say essentials is very good but sadly, it is the only plugin available with such functions
well not really. you could use Skript and make your own plugin. that'll also be better than essentials ||/s :))))||
what about you fuck off @broken elbow
who's off? is that your mom?
nah
=
/
Use https://paste.helpch.at/ for errors, logs and configs. So we don't spam the discord.
I get this error when my plugin loads
It's "How about you fuck off @broken elbow" not "What about you fuck off @broken elbow"
On line 46 thiss is the code:
New bouwCommand(this);
And line 16 of the bouwcommand classs this is the codee
Public bouwCommand(Bouwpixel plugin) {
plugin.getCommand("bouw").setExecutor(this);
}
But idk whats wrong
Did you register the command in the plugin.yml?
Omfg
I'm so dumb
And stupid
Thanks i try it
I've tried it but the same error pops up
Lol
I've plugman deleted
The same error pops up
Commands:
bouw:
This is my plugin.yml commands section
It works
Thx!
Does worldguard api not have a method for checking a player is within a specific region? Can't find it in the guide.
I get this error when i pickup an item
Use https://paste.helpch.at/ for errors, logs and configs. So we don't spam the discord.
Code: public void pickupEvent(PlayerPickupItemEvent e) { Player p = e.getPlayer(); if (Bouwpixel.bouwers.contains(p.getUniqueId())) { e.setCancelled(true); if (this.COOLDOWN_pickup.contains(p.getUniqueId())) return; this.COOLDOWN_pickup.add(p.getUniqueId()); Bukkit.getServer().getScheduler().runTaskLater((Plugin)Bouwpixel.get(), () -> { if (p == null) return; this.COOLDOWN_pickup.remove(p.getUniqueId()); }, 100L); p.sendMessage(Utils.chat(Bouwpixel.get().getConfig().getString("interactions.items.pickup")));
is that the entire error? bcz it again looks like you only sent part of it.
Yup i dont have nitro and then i cant send the whole error
Wait i gonna upload him
This is the whole error
well it seems like Bouwpixel.get().getConfig().getString("interactions.items.pickup") returns null.
Thx i'm gonna check it
Hey I am stuck with an idea. I want to make sort of a skyblock-ish minigame. However think of it more as hypixels skyblock with an RPG element. However I am stuck at the thought how I would handle the worlds. Since I am not gonna do a server per person since it wouldn't be scalable.
I was thinking something along the lines of storing worlds in a blobstore, but this would have a lot of lag when loading in. Anyone know what's the best way to tackle this issue? The best way to manage saving and loading of a players island?
Keep in mind multiple servers are assigned to handle the skyblocks. ^
Does someone know why slf4j's logger doesnt work with "debug" in paper 1.17.1?
Only the top line gets printed to console
LOGGER.info("INFO LOG");
LOGGER.debug("DEBUG LOG");
because the debug logger isnt enabled by default
you have to change the logging config
which is a horrendous experience
that nobody deserves to go through
Oh lol, so only info and error works?
and warn
ah nice
iirc debug will go to the .log files
I guess I wont need more than that
but not console
Oh that's pretty nice ngl
you can try ASWM
Thanks for your reply, what does ASWM stand for then I'll look into it
maybe you can customise it a bit
but id wait for the rewrite
Will look into it, maybe it could help me out big time
Hello i need help
How do i import the class location from Spigot API
my "extends JavaPlugin" is red
I added the dependancy
"board is null"
public void updateDefaultBoard(FastBoard board) {
board.updateLines( //Line 82
"",
"Players: " + getServer().getOnlinePlayers().size(),
"",
"Kills: " /* + board.getPlayer().getStatistic(Statistic.PLAYER_KILLS)*/,
""
);
}
Inside runnable
scoreboardManager.updateDefaultBoard(scoreboardManager.getDefaultBoard(player)); // Line 72
onJoin event
FastBoard defaultBoard = new FastBoard(player);
defaultBoard.updateTitle(ChatColor.BLUE + "Survival");
this.defaultBoards.put(player.getUniqueId(), defaultBoard);
yo help me
Are you using gradle or maven
Intellj
he's probably not using any. just the things offered by IJ
Ye
its just red bro
i added the spigot.jar as a dependancy but it wont work
why would i need a build tool
also my module sdk is openjdk-17
idk if thats like
bad
I would recommend getting a build tool - https://www.jetbrains.com/help/idea/gradle.html#gradle_import_project_start
idk i can't even get like the most basic thing to work
JavaPlugin is just red
i followed like 4 tutorials
its just red
Yes, it's because spigot isn't implementing correctly, not sure how to do this without a build tool. A build tool basically handles all this.
What method should i use to take instance of the main class?
private static Main INSTANCE;
public static Main getInstance() {
return INSTANCE;
}
``` This is the easiest way i think but i have heard that using static like this is bad or using it in util classes where you use static alot? Is it bad practice or does it actually affect something else, like performance? I dont use static in util classes and is that good or should i switch to using static because it doesnt affect anything or does it?
Util classes
Are there to be static
Because they should serve utilities not bound to a class
And for the main, you just pass it around with dependency injections
?di
Dependency Injection
Dependency Injection is a way of providing objects with the objects they need ("dependencies"). This is usually done with a constructor, but can also be done for individual methods
Read more here: https://en.m.wikipedia.org/wiki/Dependency_injection
Dependency Injection in Java:
https://paste.helpch.at/yijawupoju.java
Dependency Injection in Kotlin:
https://paste.helpch.at/esogakutod.kt
Anyone know how to cancel moving an item using 1-9 keys? I've canceled moving the item in the inventory, just doesn't cancel 1-9 keys for some reason, even though pretty sure it calls on the same event
Trying to learn Java and got a basic plugin set up that just shows starting and stopping in console.
Can someone code a command that I can put in my main.java that would like make /ping command (and answers to only that players "pong!"). This way I can understand more how commands work, thanks.
It doesnt say anything about sending a message to a player
if (!(sender instanceof Player)) {
Bukkit.getLogger.info("cmd is for players only!!!!!!!!")
return true;
}
Player player = (Player) sender;
player.sendMessage("lol");
smth like that
you are so close xdd
now?
dont you need to use the
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)```
thing?
How can I
if (sender instanceof Player player) {
player.sendMessage("lol");
} else return true;
what is going on
yes you do
it should look like this
I recommend to learn Java basics (just basics, you dont need to be Java pro) before making Bukkit plugins
//commands/PingCommand.java
public class PingCommand implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
Bukkit.getLogger.info("cmd is for players only!!!!!!!!")
return true;
}
Player player = (Player) sender;
player.sendMessage("lol");
}
}
//MainClassName.java
public void onEnable() {
registerCommands();
}
private void registerCommands() {
getCommand("ping").setExecutor(new PingCommand());
}
//plugin.yml
name: ...
version: ...
main: ...
commands:
ping:
damn
also use https://mf.mattstudios.me/mf/mf-1
using libraries and frameworks is likely not the best idea when someone is just starting to learn all of this stuff with little java experience
jesus fucking christ @cinder forum. I'll start timing out if you don't stop with this spam

I understand #off-topic but you took over #dev-general and now #development as well
When using a InventoryMoveItemEvent, is it possible to get the name of the inventory without using Inventory#getViewers?
I want to get the name of the inventory, but what if no one is looking in the inventory at that time?
Does not that compare contents as well?
no
Wat
it compares the (underlying) inventory instance
Though, I want to compare the title. I have custom items, and a feature which blocks the movement of item to certain inventories, with a certain name if you wish.
So I need the title
Or can I do that with .equals()?
What?
what what
I asked if your feature works/depends on the title being a certain one
Ohh
Like, e.g. renaming a shulker box
Yeah, ig. If the plugin users wish to block the movement of items to only chests with a certain name they should be able to
Is what I want
And this goes for movement through hoppers as well
A.k.a. a player might not be watching the inventory
Right, idk if the best way but a good one then is probably to store inventories in a Set<Inventory>, and then in the event check if Set#contains
Could I not use a switch, check the block type. And use Dispenser, Chest or whatever to get the name?
The thing is that inventories themselves don't have a title really
Bukkit is just garbage
yeah
...
This
:d
I mean, uhhhh
Ig I have to lol
Btw, should not InventoryMoveItemEvent activate when a player moves an item to another inventory?
thanks and is it okay still that i am calling a static method from another class everytime i use sendMessage or need anything from my config files? i made my messages config file getConfig method static. does this serve as an util?
But you get it form an instance, dont you
ye i thnk so
yeah
Nope, that's covered by InventoryClickEvent
But Called when some entity or block (e.g. hopper) tries to move items directly from one inventory to another.?
Why...
probably things like villagers "using" the inventory
idk
bukkit's inventory api is shite
Indeed lol
Also, how tf does this print false System.out.println(Bukkit.createInventory(null, 9, "Hi").equals(Bukkit.createInventory(null, 9, "Hi")));?
the inventory class must not be overriding the .equals method
definitely not
Ik
so you can technically use it on any objects
lol
No proof
the default .equals() method actually just uses == itself apparently, makes sense
I forgot that using Bukkit.createInventory creates a new inv instance
ye
So how do I know for sure that the clicked inv is from my plugin?
If .equals does not work I mean
Do I have to use titles
Or like items with nbt tags or smth
great question
i've never had that issue because i always end up having a map of <uuid, inventory> or whatever, so i already know the inv is mine
Aahh
I have a GUI tho
So...
I mean, I can compare the items in the clicked inv to the real GUI inv ig
But that still feels to dumb
Why doesn't the inv class override .equals, so dumb
i've been implementing a gui lib myself for abit
the solution i decided on was just to check if the item has a certain label whenever the player clicks on it in an inventory
it does
o
Again, using equals compares the underlying inventory instance
Why does this print false then System.out.println(Bukkit.createInventory(null, 9, "Hi").equals(Bukkit.createInventory(null, 9, "Hi")));?
.
it doesn't check contents or titles
Ohh
it's a library
wait are you sure it does
I'm 10000% certain
when i click to view the method code it takes me to the object class's .equals
So to verify an inv, with different instances, you can't use .equals. Bummer, ig titles it is
because it's not defined in the interface
but the implementation
which is not api
i see
@Override
public boolean equals(final Object obj) {
return obj instanceof CraftInventory && ((CraftInventory) obj).inventory.equals(this.inventory);
}
๐ฎ
is this where we get the dev builds for Deluxechat?
No
Hello, so I'm trying to cancel the movement of a diamond pickaxe in my inventory, I don't want to be able to move it from any slot that it's originally given in, I successfully canceled the ability to click on the pickaxe, and I've canceled the ability to shift-click the pickaxe, and using the number keys to move the item in my hotbar, but, I can still move the pickaxe to my inventory if it's in my hotbar, lets say the pickaxe is in slot 1, if I click 1 on an empty spot in my inventory, the pickaxe goes there, and then it's stuck there
Does anyone know how I can stop that from happening as well?
https://github.com/dkim19375/ItemMoveDetectionLib/blob/master/src/main/java/me/dkim19375/itemmovedetectionlib/listener/ItemMoveListeners.java#L186-L204
something like this (using InventoryClickEvent#getHotbarButton)
Hmm.. I have no idea how to implement this in my current code yet, lol
so if the event type is when a player presses a number in their inventory, you have to check if the pickaxe is in that numbered slot
if it is, then cancel the event
Ah
and so InventoryClickEvent#getHotbarButton would return a number from 0-8
0 being the first slot in the hotbar
and -1 if it's not a hotbar numkey action
Hmm, I have like, a ton of checks for specific items right, like, in my config I have each type of pickaxe with a true or false to determine if that should be enabled, and if it's enabled, it cancels the event
I guess what I don't understand is if I should check for what you're saying, inside that area, like under each pickaxe, or before it, and still check for each pickaxe.. I will try before it
Yeah ^ I'm completely stumped
Okay, so I've got it to cancel for every item, but I can't figure out how to check for a specific item
if (e.getClick() == ClickType.NUMBER_KEY) {
if (e.getCurrentItem().getType().equals(Material.DIAMOND_PICKAXE)) {
e.setCancelled(true);
}
}
For example, this does not work
But, obviously, if I remove that second check then it does work
I am currently attempting to swap the if's
Didn't work
I don't get this
So the opposite of that works to stop pressing numbers on the item, but not to stop moving the item to an empty spot you clicked..
Okay well I know what I have to do but I don't know how to do it
because you have to check what number it is
and if the number's slot is the diamond pickaxe, then set cancelled
does anyone know how to fix this error: The AureliumSkills API is not loaded yet with the AureliumSkills plugin?
pls ping me if u have a solution bc i gtg thx ๐
anything?
just load your plugin after Aurelium Skills
its added as a depend in plugin.yml
How do I get JUST the playername in 1.17.1 paper? Instead of this crap
kek
I'm assuming they actually want the display name
I do
but .displayName() also gets that
yeah. it returns a component
ye
Can I get the displayname based on that or just .getName() ?
@@NotNull
Componentๆฑ) compact()```
Create a new component with any redundant style elements or children removed.
4.9.0
the optimized component
kek
anyone able to help me? ^
Sooo getName() lol
if you want the name, yes
I don't think there's a content method for Component
hmm actually
As in displayname? I wan't nothing other than that
the name the player has when selecting it
Should be good
@wheat carbon nice symbol
wew
only if they were separated ffs
Gotta love it
@NotNull(@NotNull)
also wtf is going on here?
It probably broke on the double @NotNull
This still adds to the original set right? Just to be sure
TreeSet<PlayerTime> times = parkourPlugin.getPlayerTimes();
if(times.isEmpty()) {
times.add(newTime);
}
When creating a copy of it
Quick typing the basic template in exams where im not allowed an IDE or copy/paste
no, copies are new objects
Oh so if I use the getter afterwards in a different class I won't get the same contents in the set?
if you getter returns a copy, no
the getter returns the actual set, not a copy.
private final TreeSet<PlayerTime> playerTimes = new TreeSet<>();
public TreeSet<PlayerTime> getPlayerTimes() {
return playerTimes;
}
that does not return a copy
Yeah but this doesnt create a copy rightTreeSet<PlayerTime> times = parkourPlugin.getPlayerTimes();
I just wanted to avoid calling the getter all the time to get the set
no, it doesn't create a copy
you assign the value of getPlayerTimes() to times, like a shortcut
Hey is there a way we can get the amount of xp player had before he died?
Why does this not work? It only cancels "left click moving"/drag and drop
@EventHandler(priority = EventPriority.HIGHEST)
public void onInventoryClick(InventoryClickEvent event) {
Player player = (Player) event.getWhoClicked();
Artifact a = Artifact.getArtifact(event.getCurrentItem());
// Return if the clicked item wasn't an artifact or if players
// may move the artifact around in the inventory
if (a == null || a.getConfig().getBoolean("Traits.AllowInventoryMove"))
return;
// Cancel the event
event.setCancelled(true);
player.closeInventory();
}```
Use inventory interact event
Oh, I'm not that smart
you can use abstract events?
if your doing that i would suggest you cancel the inventorydrag event.
because i had an issue where if i dragged an item it wouldnt cancel it.
Wait, how do I get the item when using a inventory interact event?
Is it even possible?
sorry mb, i don't think InventoryInteractEvent works
Wait no, I can't get the clicked item
Why?
I want to get the item that is clicked though
probably cause its an abstract event.
yep
Frick, how do I cancel the item moving then...
with the InventoryClickEvent and InventoryDragEvent
when it comes to my inventories i just cancel drag event.
The Shift-Click and numpad moving though?
That isn't covered by InventoryDragEvent, right?
you cant drag with numpad or shiftclick
you have to be holding the item to drag it
you cant drag with numpad or shiftclick
Yeah, that is what I mean. So how do I cancel it?
Since this does not work for shift click and numpad move
send some debug messages of the get result of the event to yourself and see whats different and figure out a solution from there
I know that click types and inv actions are a thing. Just, shouldn't the event I made be global?
there might be cases where your check doesnt actually function
Obviously
im going to guess that a is returning null when you do certain things
which will be why it doesnt work for those specific cases where you say it doesnt work.
Ig, I'll do some debugging. Thanks
Ok, so everything seems to work fine. As long as you are not in creative?
In those cases, the item will dupe. The item will stay in its original slot, and still make a copy in the new slot?
hi, why is this not working? "%player_has_permission_permission.test%" (JavaScript PAPI)
im not entirely sure.
if you want help you should submit your js content
cause asking why it doesnt work doesnt exxactly help
also javascript placeholders have a specific string before your placeholder name
i think yours would be %javascript_player_has_permission_permission.test%
For MongoDB what exactly is the databasename?
Would it be the project name? Or "Cluster0" or what?
Referring to this
var haspermission = "%player_has_permission_permission.test%";
function hasPermission() {
return haspermission
}
hasPermission();
should return yes or no but returns nothing
BukkitPlayer.hasPermission("permission.test")
ingenious
๐ ๐ฅฒ
I'm running into this error https://paste.helpch.at/ucurujutap.css
return ParkourPlugin.GSON.toJson(this);
Is it because this is a comparable?
This is the object I want to serialize https://paste.helpch.at/tupimiribe.java
Unable to make field private final long java.time.Duration.seconds accessible: module java.base does not "opens java.time" to unnamed module @223f3642
Yeah so I need a custom TypeAdapter I assume
That's what I'm tying to create at least, but is it even possible to have a custom typeadapter for an immutable class?
Since I need something like this
if ("name".equals(fieldname)) {
//move to next token
token = in.peek();
playerTime.setName(in.nextString());
}
what even is that
Gson - Custom Type Adapters, Gson performs the serialization/deserialization of objects using its inbuilt adapters. It also supports custom adapters. Letรขยยs discuss how you can create a
Trying to create the read function in the TypeAdapter
Wdym?
for instance, if you have a Location in your class and create an adapter for it (since the world can't be serialized by default), GSON will then be able to serialize your class without an adapter for it
Gotta go eat, I'll be back right after
Yeah, but I need an adapter then, are there ones out there that are able to serialize comparable classes? I assume it's the fact that it's comparable that's the issue, or maybe the Duration, idk
Well, comparable objects are nothing more than objects with a compareTo method. GSON (de)serialize only fields, so that wont be a problem.
But ye, the problem looks like is Duration.
Hmm, so you'd recommend finding a public adapter? Or creating a custom one
Found this, just gotta figure out how to use it now https://solidfire.github.io/solidfire-sdk-java/docs/com/solidfire/core/serialization/DurationAdapter.html
Thats for org.joda.time.Duration
Oh... Not sure what that means lol but I guess you're saying that it won't work
oh wait I see what you mean
You have a java.time.Duration object
yeah, gotta create a custom adapter I guess ://
Is not so hard, is basically a class that you use to tell Gson how you want to serialize or deserialize an object
Yeah that's what I was trying to do here
Pretty sure my serializing method works, just not the deserializing method
Not sure how to make it since my class is immutable, and, well, I got told it should stay immutable
There's an example of deserialization,
So that's better than creating a custom adapter? https://www.tutorialspoint.com/gson/gson_custom_adapters.htm
Gson - Custom Type Adapters, Gson performs the serialization/deserialization of objects using its inbuilt adapters. It also supports custom adapters. Letรขยยs discuss how you can create a
I'm not sure about that, they probably have a similar output
Wait... I might've found an even easier solution, instead of storing the actual duration, couldn't I just store a long that contains duration.toSeconds() ? Not sure if it would work with the TreeSet or not though
I might not be able to convert that to millis so nah. I'll just try and create a deserializer
Noooo don't use the Json(De)Serializer
1) You can't. JsonSerializer and JsonDeserializer are the old converter way. New applications should use TypeAdapter, which has a superset of funcionality.
2) Assuming you mean JavaFX's ObjectProperty<T> and you want to extract T's class.
You can access the Type inside TypeToken easily with TypeToken#getType().
I will give the example with List<String> which is the same idea but easily testable.
Just found this, so TypeAdapter it is ig
yeah the JsonSerializer/Deserializer is essentially deprecated
Can you help with the deserialization part then?...
I've managed to create the serialization I think
you think?
Good to know
Well, can't test without the deserializer really
@Override
public void write(JsonWriter out, PlayerTime value) throws IOException {
out.beginObject();
out.name("name");
out.value(value.getUsername());
out.name("time");
out.value(value.getDuration().toSeconds() + "." + value.getDuration().toMillis() + "s");
out.endObject();
}
Not sure if it's wrong
or add two properties, seconds and ms
eeh toMillis doesn't give you the milliseconds "part" of the duration
^
it gives you the whole duration as millis
and you shouldn't store it to be "human readable"
you should store it as easily to work as data
i.e. just store toMillis, no "1.23s" or "123ms" etc
So just ```java
out.name("time");
out.value(value.getDuration().toMillis());
?
yeah looks about right
nah
Good good, so for the reader, I need to pass in the constructor for the PlayerTime object somehow, how can I do that within the adapter?
first read, then construct
Huh? So I'm trying to follow a guide where they've done something like this
if("time".equals(fieldname)) {
//move to next token
token = in.peek();
playerTime.setSmth(in.nextInt());
}
But my object is immutable so what can I do?
Read from where though?
Not sure how it works
from the.. reader?
int veryImportantValue = 0;
//blah blah whatever
if (something) {
veryImportantValue = reader.nextInt();
}
// ...
.. new VeryImportantObject(veryImportantValue);
Doesn't my object need to be mutable then? Atm it's immutable
Since I'm adding 2 values to the constructor
why would that make it mutable
first read all the necessary data
put them into local variables
then once you're done with the reader, call the constructor, return the instance
nothing in here suggests that VeryImportantObject is mutable
