#help-development
1 messages · Page 1766 of 1
and I have a licensing system built in
just trying to make sure people don't remove the licensing
They will even with obfuscation if they want to
as the plugin uses a subscription model, as I provide api etc
yes but it's harder..
Tbh I don't care about obfuscation.
all license systems can be bypassed
not really.. unless you do license check everywhere which is definetly just trash in code
I know but it's harder
If somebody wants to bypass it theyll do it
duh, but ya know..
subscription model for a plugin...
Subscriptions arent allowed on spigot i think
are they?
I wanna bypass it just for fun and to prove a point, but I dunno if that's exactly guideline-safe.
well it doesnt matter since spigot doesnt allow subscriptions
oh fun
i know the tos
why ask on our discord then
¯_(ツ)_/¯
Spigot-related project, why not consult Spigot?
Like
Where else are you going to go?
"The Discord for people who don't know how obfuscation works"?
Mcm4r***
Good luck trying to find a server that specific.
dude
this is for spigotapi
nopt for the spigotmc website
sooo
i'm using spigotapi
but not gonna publish it on spigotmc
i dont think spigot api lets you obfuscate your code 😉
itself ofc
If you really want waste your money on obfuscator and obfuscate your java program
I dont see how connected it is with spigot api
it sure does
GPL 3 requires you give source if requested.
yeah that itself breaks your subscription model
And you cannot sublicense or relicense or whatever, you must license under GPL 3 if you use a project that is licensed under GPL 3.
under the same license
You could obfuscate your binaries, but you still have to provide source if asked.
smh..
Feel free to obfuscate binaries yea
So, there wouldn't really be a point.
also feel free to sell them
but source code is something different
doesnt gpl say that if you contribute to the project you get copyrights?
patent rights*
cool dont post that shit here
if someone else needs help with it
they now also have the solution
calm your damn voice and stop giving this aggressive tone.
Theres no voice, this is chat, how do you know how aggressive my tone is?
Have a good day.
Connotation.
Some people can pick out tones even from text.
If you are worried about my tone feel free to hop on vc
I'm good, have a good day.
Y'know if this dude gave me an obfuscated binary, I could totally find the line which initializes his licensing :)
^
Maow lets do a speedrun
And I want to prove to you that no matter what protections you make, it is all futile in the end.
Lets get somebody to make a license system in a hello world plugin
and we will remove it as fast as possible
hell yeah
VotingPlugin
?
getOfflinePlayer
with a string as parameter is deprecated
read the deprecation note. Deprecated doesnt always mean doesnt work
but imo the deprecation here is absolutely unecessary
Persistent storage of users should be by UUID as names are no longer unique past a single session.
are you doing persistent storage?
i'm trying to ban an (offline)player from a chatchannel
then just use deprecated method
oki
y'know
my code literally
GLOWS
when you look at it
it is that good
squeaky-clean
:glow-squid:
glowsquid 🦑🎆
it doesnt prevent stealing
why do they even post plugin to a english forum...?
see reviews
there are x deobfuscators
technically code isn't source-code after you decompile it
therefore, either you need access to the original codebase, or you have to be incredibly lucky to get a 1:1 match of the original code
well
in my own region i get this
and when i clone a github repo...
it just sad
do hashmap info get deleted when i restart or reload a server?
I would wrap your https:// links in quotation marks
Or, really, all of your URL strings
e.g. VoteURL: "https://minecraftlist.org/vote/26109"
How can i change the name of a player above his head?
Does equals(Object) in org.bukkit.Location compare objects or the actual location values? If the latter, does it only compare world, x, y and z or also yaw and pitch?
can i compare two players with ==?
What would you compare of thus player?
i just want to check if they are the same
I'm pretty sure you can
Use == as I don't think multiple instances of one player can exist.
^ yes
Using equals would probably do identity comparison anyways, and if not, would be much less efficient.
You can also compare their UUIDs, I suppose.
yes
PreparedStatement checkX = connection.prepareStatement("SELECT * from FastTravel WHERE posx >= '" + (posX - distance) + "' AND posx <= '" + (posX + distance) + "' AND world = '" + world + "';");
sender.sendMessage("SELECT * from FastTravel WHERE posx >= '" + (posX - distance) + "' AND posx <= '" + (posX + distance) + "' AND world = '" + world + "';");
setX = checkX.getResultSet();
if (setX == null) {
}
else if(setX.next()) {
How comes the else if is always false, even if I input the message i get via sender.sendMessage() in the mysql console and it returns values?!?
nvm...
If you only have one entry in the ResultSet calling next() will return false
i needed to do executeQuery, not getResultSet
i dunno why it is like that, but now it works
bc a PreparedStatement is one that is compiled but not executed
cache via prepared statements if used more than once as it offers higher performance
is
if (Bukkit.getOfflinePlayer(uuid).isOnline()) {
Bukkit.getPlayer(uuid).sendMessage("something");
}```
the same as
```java
if (Bukkit.getPlayer(uuid) != null) {
Bukkit.getPlayer(uuid).sendMessage("something");
}```
?
no
whats the difference?
getplayer... only return if the player is online..? while the getofflineplayer do both i think
nm, it is, I was wrong in assuming the getOfflinePlayer could return null. It can;t
ah oki thanks
How can i change the name of a player above his head?
scoreboards
I mean with packets sry
1 ping lmao
the guy has a lan connection to the server or smth
:c
welp
but that 1ms is only in my country
other country ping = garbage...
Hey there! What's the equivalent of Bukkit.dispatchCommand on bungee? I want to perform a command on the bungee console
again, using scoreboard packets
But why packets?
what did google say?
Hi, I'm starting to make a plugin for my server and the plugin is based on roleplay (Something like FiveM). As this is my first time starting one I would like to see if anyone is willing to help me
possibly willing to help with a few things and questions. Youre gonna have to elaborate on the idea and how you want it to work tho
if this is your first plugin and you dont know java you need to check a few things first
?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.
and watch the tutorials from TheSourceCode
wew this is awesome
Can you give me an example?
Thanks
wiat thats so cool lmao
you can keep me in mind tho. always glad to help out 🙂
[16:08:42 ERROR]: [null] Votifier was not able to bind to /0.0.0.0:2575
This appears even tho my port is open
rn i'm using static help messages so lets change to a componentbuilder :kekw:
google it
Reject legacy color codes and move to components!
(adventure noises)
well its still kinda awesome
IF the port is really open and it can;t bind, you have somethign already on that port
uhh i color my components with chatcolor.translateshit
that looks awesome, saved.
What does utils.colorize do
public static String colorize(String args) {
return ChatColor.translateAlternateColorCodes('&', ChatColor.GRAY + args);
}
):
Use fromLegacyText
How do I read a JSON value from MySQL into a JSONArray?
otherwise the event would also be on"to create a home at your..."
Maybe use Gson to deserialize
Or parse rather
so I read the json as a string, how do I turn it directly into an iterable array?
unless I could just replace the ] at the end with the value i want to append
😂
Uh well I don’t think there’s such a type like JSONArray JSONObject and so on
That’s for nosql and unstructured data stuff
then what the fuck do I use
I mean what
I'm totally not using json-simple in a project I'm working on rn
Any other json lib beats it gson, moshi or even Jackson?
nope
well I need something with streaming
I have to parse some giant files
but I also need to ignore like 80% of the data within them
(I also need to replace the other 20% of that data with my own data)
so y'know, injecting data into JSON files in an efficient manner basically
setX.getString("bound").replace("]", ", \"" + player.getUniqueId() + "\"]");
I am just using this now ^^
You can stream with these other libs also, it’s not a simple json only solution
Alright well I dunno how to stream with something like Gson or Jackson.
Especially since their APIs are super fucking complicated.
If you're using this to store collections in db learn about one-to-many and other db designs
there is some other json libs like fast-json
but idk if the speed is necessary
I Wonder why does moshi use annotations instead of good ol interfaces
For?
Custom type adapters..
https://github.com/square/moshi
bc it's Square
they make the weirdest of decisions
and then ship it as production code
public void onSpawn(PlayerRespawnEvent event) {
if(!plugin.getAngelEvent()) return;
Player player = event.getPlayer();
player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 1));
player.addPotionEffect(new PotionEffect(PotionEffectType.FAST_DIGGING, Integer.MAX_VALUE, 1));
System.out.println("added");
}```
Seems to print "added" to console but doesn't actually give the effects, anyone know why?
Annotations modern smort
Oh yeah, well it gives you the power to what the name is going to be, what arguments you can take and so on, I do like interface way Gson has it but it’s probably more flexible this way moshi got it.
I mean you can still do that with interfaces
Demonstrate an example?
Pretty sure Gson doesn’t allow you to specify something else than a JsonReader/JsonWriter for TypeAdapter but feel free to prove me wrong
Guess you could have something like interface TypeAdapter<T,R,W> but that’s going to make the api design complicated unnecessarily.
X,Y,Z > T, R, W
¯_(ツ)_/¯
is it worth making something static if there is only one instance of that class?
No not really
oki
it is possible to add jvm arguments when starting the plugin?
why
Afaik no, maybe with a specific jvm implementation some of the flags will be changeable
I have a java module problem in my plugin, the only thing that helped now is adding the --add-opens=java.base/java.lang.reflect=ALL-UNNAMED flag on server startup, I don't have any idea how can i fix that. Problem: module java.base does not open java.lang.reflect to unnamed module (jdk 16)
whats the x/y here? what do you need from java.lang.reflect
i need to set any default attributes for my own entity
someone recommended me this way
wtf
try {
var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
final VarHandle MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class);
final Field field = AttributeDefaults.class.getDeclaredField("b");
MODIFIERS.set(field, (int) MODIFIERS.get(field) & ~Modifier.FINAL);
field.setAccessible(true);
Map<EntityTypes<?>, AttributeProvider> attributes = new HashMap<>((Map<EntityTypes<?>, AttributeProvider>)field.get(null));
attributes.put(type, EntityInsentient.w().a());
field.set(null, attributes);
field.setAccessible(false);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}```
Isn’t there api for this? lol
I tried to use getDeclaredField on Field.class but in jdk 16 it is not possible
modifiers
Java internals are being encapsulated to make it more secure
(there's Attributable#registerAttribute on paper)
yup
private static final Map<EntityTypes<? extends EntityLiving>, AttributeProvider> b;
Pretty sure setAccessible overrides it’s final state for reflective operations
At least it did on some jdk versions I believe
Oh it’s static
nvm
so maybe there is some other option how can i fix this problem or set the attributes in a different way?
how to solve it
why i can't use this https://cdn.discordapp.com/attachments/871420093937123379/908337799118323763/unknown.png
help
i want to solve it
How can I open a sign and get player input?
NMS and Packets
There is a openSign function for players
But you can't get input with that though, can you?
Not in Spigot
That would be Paper or some other fork
please dont
Why not?
You don't even know what he's doing lmfao
He could be making editable signs
^^^^
ah then sorry
i just spent a lots of time on packet based anvil n sign guis, and, as result nothing but annoyed players
Command block allows way more chars 😉
they are fully clientside starting from 1.8 iirc
Its possible. I don't have the source off hand sorry.
I've seen it in 1.14
Well, there's only one packet i found for Command Blocks:
https://wiki.vg/Protocol#Update_Command_Block
and its being sent by client, on command block update
should i store a static cache of instances in its class or at some other place?
i'm keeping a cache of chatplayer objects
like with lists that store the channels they are in
then make ChatPlayerManager class or smth
another class..
ok
eh never personally enjoyed SRP
probably one of the worst aspects of OOP bc of classloading overhead
what is srp?
and also how code can sometimes get messier from an abundance of classes
Single Responsibility Principle
ah
you, like, dont do a seperate class for every function, but the ChatPlayer itself shoudlnt manage players
performance optimization async multithreading overhead 😡
lets make everything static 🤓
srp is absolutely fine and reasonable aspect
congratulations, you are now a pure imperative language
whatever that means
I don't think such a thing even exists
but like making everything static means you have no state
you can go to the pascal or idk with this thoughts
no cache
performance go 📉 📉 📉 📉 OH SHIT
in fact its just this
computeIfAbsent
it will:
- check if a value exists in the map
- if it doesn't, it will call a lambda you have passed to it
- it will set the key to the new value from that lambda
- if the value did exist, return it, if it didn't, return the lambda's value
it's much more efficient and is a single line
lambdas are nice bc they're lazy, they only execute when necessary
you can use it like
return playerCache.computeIfAbsent(uuid, (key) -> new ChatPlayer(this, uuid));
the lambda takes a parameter
what is the key in the lambda though?
it's also conventional to use the parameter name ignored if it is unnecessary for that lambda
oh
haha memory leak go brr
uhu
sooo there shouldn't be a memleak
yeah but how often is that cache wiped
You're gonna end up like Jobs that caches all blocks for anti-dupe purposes and never wipes the cache
ah shit
Is is possible with the BlockBreakEvent to check which side of the block you broke it from?
consumed 5gb on my survival server before I forked it and started wiping it some times
why not just k -> new ChatPlayer(this, k) then?
event.getBlockFace ?
I mean you could do that, it makes no difference tho
If that doesn't exist, cache the last clicked block face via PlayerInteractEvent
actually it makes a small difference
you wouldnt need the parentheses around the (key) since theres only one argument to the lambda iirc
oh right
I usually put the parentheses for readability
I don’t understand json files, how do they work?
helps me understand where it stards
but ye the method generated by the compiler for that lambda will have an additional parameter if you capture outside variables I believe?
They're basically YML with braces
Well what it lets me do is e.getBlock.getFace() but then requires a block argument which doesnt make sense to me because the block is already being given
You can also raytrace the clicked face
LivingEntity#raytraceBlocks
It returns 2 blocks
get the face relative to one another
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
so basically it ends up being lambda$getChatPlayer$0(UUID key, UUID uuid) as opposed to just UUID key I think
Which is about as accurate as it gets
Huh
learning new things today
when capturing a variable outside of the lambda, it must add a new parameter to that method
Thought lambdas made an anonymous internal class
ClassNameHere$1#someMethod(ClassType object, ClassType2 object2)
one sec
A lambda just makes an anonymous class
An anonymous class is just an internal class with a $<number> in bytecode iirc, that implements the method
lambdas are fun
Don't use the term "anonymous class," it's actually used by MethodHandles.Lookup to refer to classes that cannot be found by the classloader iirc.
Plus, that's not true.
afaik
This beginner Java tutorial describes fundamentals of programming in the Java programming language
Lemme look at the bytecode.
oh right those
yeah those are just inline class implementations
They're called Anonymous classes according to Oracle
that's bc they can't be referred to
....
lambdas work different from Anonymous classes
Lambdas seem to be based on Anonymous classes
The parameters end up on the left side of the lambda
The return value is the same as the anonymous method
so let's take the class
import java.util.function.Consumer;
public class CompiledLambda {
public static void main(String[] args) {
final String other = "fuck";
final Consumer<String> c = (s) -> {
System.out.println(other);
System.out.println(s);
};
}
}
public void doSomething(Object one, int two, String three) {
return three.length() + two + one.hashCode();
}
gets converted to
(one, two, three) -> three.length() + two + one.hashCode()
string fuck 🤓
The formatting for the name here is
lambda$<declaring method>$<lambda index>
it is this way to avoid conflicts
and also provide better debug information, I presume
but right here is where that Consumer is created and stored
#0 referring to bootstrap method 0, which points to
a LambdaMetafactory.metafactory call which will return a Consumer for that lambda method
(that's public API btw, fun fact)
you can see by the second method argument that it references lambda$main$0
Can someone explain this? 🤨
that is specifically a method handle embedded in the constant table of the class that references the lambda method
so yeah
I believe metafactory actually creates a Consumer that calls the method?
but I don't know, I haven't looked into it
✨ Exploring the JVM with Maow ✨
anyway that's also why lambdas are pretty fast
they're literally just dynamic method invocations
well, Class.forName is our friend
but one thing you can't do with LambdaMetafactory is loop through all methods in a class
or access fields
like, if you know exact method you need you may use it
and you'd have to have functional interfaces for each possible method type
(my solution? classloader hacks + class generation, haven't tested it yet but it would be fun)
(you would have to declare the class on the Lookup you use for the metafactory)
but yeah LambdaMetafactory is fast
it is about as fast as direct access
you have basically 3 reflective options:
Reflection - Fast lookup, slow invocation, good for one-time operations.
MethodHandle - Slow lookup, fast invocation, great when caching commonly-run methods. (I have had some struggles with private methods in the past though, look out)
LambdaMetafactory - Fast lookup, fast invocation, makes code harder to read/work with, but is a good tool if you have a performance-tight application.
(Technically metafactory is internal-ish API, since it's used by the JVM to retrieve functional interfaces for lambda methods, but is required to be public due to access restrictions)
anyway sorry for the ramble I just love talking about bytecode and shit
If i use .setHealth(0); whilst the player is in a fight, does the attacker still get the kill?
What exactly are you trying to do?
i have a OnDeath listener for way 2 players fight stuff happens, im trynig to check if their y is below a certain coord and if it is, they die
kinda like a sumo duel
Ah ok
Ill try it rn
Use the above method, passing their health and teh other player as the entity
Anyone knows why entities do not despawn when I remove them in onDisable?
Might be cause onDisable runs on the last tick
What can I do?
runTaskLater?
Like, call the remove() method and then do runTaskLater with no content
no
Ok
you can;t use teh scheduler in onDisable
ok
onDisable is so your plugin can clean up after itself, not make changes to the world
Yea alright, but I still need to remove entities
Hi i just downloaded a Plugin on Spigot and there is a error when the Plugin tries to load. Could not load 'plugins/randomitem-1.0.jar' in folder 'plugins'
org.bukkit.plugin.InvalidPluginException: Unsupported API version 1.17. But do i really need to update my Server Version to 1.17 ? Is there any other way ? I am using 1.16
Is there really no way to do it?
you cant use 1.17 plugins on 1.16
update your server (recommended) or find a 1.16 compatible version
You could technically mark the entities for removal which then gets picked up by your plugin in the next instance of the server
"technically"
Basically, I just want to remove armor stands because they obviously lose their metadata so I can't use them after a restart.
3 months ago it worked with 1.16 and the spigot page says it worked also on 1.16 but when there is no other way then i use 1.17
Hey does multiverse prevent entities from spawning in the overworld in 1.17.1?
whenever i use the exit portal in the end
if I have a few blocks can i just initialize a list with the blocks or do i individually have to add each block after initializing it
Your question is very vague
You can add blocks to a list at any time
depending on how you create the list
I dont know how to word it so like I am recording a ton of blocks as variable and I want to make a list of them can i just make an arraylist and put them all in while initializing it in one line or after I make the arraylist do I have to add them one by one with arraylist.add
either is fine
if theyre already in a list you can initialize the new list with the contents of the old
if you are adding Blocks you may be better using a Set over a List
How do I do it when initializing it I cant seem to find the correct format for it
thats probably the better way
Lists (especially very long ones) can be hard to find stuff in and add stuff to
attributes
okt y
edit the max health in the attributes and then dont forget to set the actual health to the max health
helpers
Also, could it be that you cant spawn entities in onEnable?
you can. I just delay it a bit so theres no trouble
I delayed it 40 ticks and it did nothing
40 ticks might not be enough. I did 5 or 7 seconds
depending on how long the server takes to start up it could be different
ive never had any reports of it not working. lemme get my numbers
this works for me. try it maybe
What is the difference between runTaskLater and scheduleSyncDelayedTask?
I believe for runTaskLater you have to tell it when to run it at one point
not sure tho
they are effectively the same
nvm me then, sorry
both have a delay
btw it didnt spawn
there could be a different reason other than the delay
how about you send the code in a ?paste and we look at it with you?
I believe it was when they resolved the confusing naming of the async scheduling the runTaskLater was added
Well the code is.. large
send the relevant bits
And I would need to send like 10 methods
gotta start somewhere, dont we? 🙂
Can someone help me fix my code?
Trying to display the Hardcore Death-screen (Spectate World | Title Screen) after someone dies. Without the difficulty actually being hardcore.
@EventHandler
public void onPlayerDeath(PlayerDeathEvent e) {
((CraftPlayer) e.getPlayer()).getHandle().b.sendPacket(new PacketPlayOutServerDifficulty(EnumDifficulty.a, false));
}
But it just doesnt display the Hardcore Death-screen.
But afaik know, the Event is triggered BEFORE the player actually dies, so idk why it doesnt work
doesnt the death event trigger before?
once the death event runs they are already dead
oh
cant be dead if you havent taken damage 🙂
i see
U can calculate the damage
what does cancelling the death event do? nothing? Unrelated, but just wondering
In the damageevent
you can generally tell when events trigger. If they are cancelable, they run before. If not they run after
If its fatal Display screen
But its cancellable
no its not
how can i see?
https://paste.md-5.net/muxevuwowa.coffeescript
coffeescript tho
thats weird, in my code i can do e.setCancelled(true); without a problem
its only one method
I'm going to bet you are not running spigot then
oh, paper changes stuff?
But wont do Shit
paper doesnt run on spigot usually
spigot runs on paper tho
literally everything is the same tho
yea the method that spawns the entity
besides this one detail
paper adds many methods.
i see
which dont work and confuse me, great
how can i calculate if the player is about to die?
in the damage event just check his healt, subtract the damage, and if below 0 thats it?
and how are you noticing that it wont spawn?
Because He Sets IT Not visible
the damage event has a few good methods for that 🙂 finalDamage i think one is called
setVisible(false)
The custom title isnt there
did you try setting the as.setVisible to true and check?
let me try
it could just be the this.display being null or something
good 🙂
but for some reason are not linked with my other stuff
wrong react
Now the weird thing: If i do /reload everything works fine
If you send more code I can help you better i believe
so if you reload the display name shows?
Use the world.spawn with the consumer
If I reload, the holograms despawn, and spawn again and are actually linked to my functionalities. If I restart the server it only spawns and stacks because the old one didnt despawn
that way you set all teh custom name etc before its put in the world
delete the old ones on disable
Bruh
maybe tag their scoreboardTags
That obviously doesnt work
why not?
Because they are not removed
cant know you already did that
Thought you read the earlier stuff in this chat
you could add them to a list and onDisable() do a for(:) for that list removing those entities
for(InfBlock b : infBlocks) {
b.saveTo(blocks);
b.getHead().despawnAll();
}
This way you make all teh changes before they are added to the world and your custom name shoudl show
no wait
It does spawn and show and everything, but the armor stands are desynced with my plugin
old stands or teh current spawned ones?
If you are having problems with old stands you should implement a session key to each
Ok so the new armor stands are spawning, even without delay
BUT, yea, old ones are also not removed when the server shuts down
when yoru plugin starts up, generate a random key (UUID.random()) or something of that sort.
Store that key in teh PDC of any stand you spawn.
whats pdc
then in the spawn event check the stand for teh key, if it has a key of the wrong value delete the stand
?pdc
that way you'll remove any old stands and only spawn ones with the correct session key
Wait so pdc is like metadata but is not gone when the server shuts down?
yes
yes
Bruh, why did I not know that 🙁
I use it for special Items that do stuff on click, coordinates for mobs to respawn and so on
How can I set default attributes for my custom entity? Currently I use that code, but that causes java module problems
private static <E extends Entity> void setDefaultAttributes(EntityTypes<E> type){
try {
var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
final VarHandle MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class);
final Field field = AttributeDefaults.class.getDeclaredField("b");
MODIFIERS.set(field, (int) MODIFIERS.get(field) & ~Modifier.FINAL);
field.setAccessible(true);
Map<EntityTypes<?>, AttributeProvider> attributes = new HashMap<>((Map<EntityTypes<?>, AttributeProvider>)field.get(null));
attributes.put(type, EntityInsentient.w().a());
field.set(null, attributes);
field.setAccessible(false);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}```
attributes are accessible within the API now
entity.getAttribute() is what I use
and then set the base value if you wanna change the max hp
why are you trying to reflect into private final fields?
But how do I know if its not a normal armor stand?
you check the pdc
you tag every armor stand you spawn via plugin
and then you check if the stand has that tag in the pdc
if it has a value in the PDC for teh key you set you allow it to spawn
right, i was dumb
if it has a key but the value is wrong, you remove it
without that plugin throws
java.lang.NullPointerException: Cannot invoke "net.minecraft.world.entity.ai.attributes.AttributeProvider.a(java.util.function.Consumer, net.minecraft.world.entity.ai.attributes.AttributeBase)" because "this.d" is null```
Okay, I'll try that 👍
Tusoo you seem to be ignoring us
Tusoo what are you trying to do?
set default attributes for my custom entity
I wont stop you, even if I could 🙂
just asking if you were gonna explain it again
entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(someDouble)); sets the max HP of an entity
One person said that this is the best way to set default attributes
It's not
they are wrong, as of 1.17
Tusoo please note the line I gave you. thats all you need to set the max HP of an entity.... then set the current HP aswell so they actually have the HP you want
How do I check if it is raining or thundering in a world? I got thundering but raining I am stumped on
if its not clear, its raining
I believe
hasStorm() tells you if its raining/snowing
hasStorm() doesn't work if its raining
it should
Well I must be doing it wrong then
if(!player.getWorld().isThundering() || !player.getWorld().hasStorm() return;
setStorm
void setStorm(boolean hasStorm)
Set whether there is a storm. A duration will be set for the new current conditions. This will implicitly call setClearWeatherDuration(int) with 0 ticks to reset the world's clear weather.
Parameters:
hasStorm - Whether there is rain and snow
That should work correct?
Should i check if a player is null in a task?
I just re-wrote it, thats not the problem -_-
I think the player might be null if the player isnt fully logged in?
Depends where you are running the task
But no player shouldn't ever really be null
Only case I have had it be null is if I am accessing an OfflinePlayer and they have never logged in
oh thanks, im running the task every second as its more optimized then using listeners
If you are wanting to check all online players use continue and not return
thanks
and 30 ticks is 1.5 seconds
if(!player.getWorld().isThundering() || !player.getWorld().hasStorm()) return; simply does not work
@eternal oxide @crimson terrace Thanks, the PDC thing works very great :)
it can be raining with no thunder
How can I do like WorldEdit : select and save temporary two locations that I can use when I do a command that requires the locations?
Store it in a variable
And to select it you can use PlayerInteractEvent
under what condition is this null?
probably when it doesnt find the player you give it
are you checkign if a Player is online or an OfflinePlayer is online?
if a player is online
if(Bukkit.getPlayer(newOwner) == null) {
sender.sendMessage(getString("messages.transfer.not-online"));
return true;
}
if(!(Bukkit.getPlayer(newOwner).isOnline())) {
sender.sendMessage(getString("messages.transfer.not-online"));
return true;
}
if you have a player object he has to be online
player object will be null when player is offline
in that case the getPlayer would return null or an exception right?
so i can scrap the second one?
you can just do if(Player)
coool
yes
thanks
np
basically that is
if(Bukkit.getPlayer(newOwner) == null) {
sender.sendMessage(getString("messages.transfer.not-online"));
return true;
}
UUID newUUID = Bukkit.getPlayerUniqueId(newOwner);
But this will 100% not cause an error?
not in Spigot
no clue its Spigot here
it is paper
it may work in paper idk
paper methods do not work on spigot
ik
it wont cause an error dw
but you can simply create a player variable and check its null if not player.getUniqueId()
it probably will be faster
How can I know if the PlayerInteractEvent is a right click or a left click?
Player player = Bukkit.getPlayer(newOwner);
if(player == null) {
sender.sendMessage(getString("messages.transfer.not-online"));
return true;
}
UUID newUUID = player.getUniqueId();
check for the action type. its an enum
you can check if the event.getAction() is Action.RIGHT_CLICK_AIR for example
at that point cant you just do if(!player)?
How do I register command arguments as syntax?
wym?
I dont know this one but my first thought would be alias
you only register root commands
he wants to autocomplete
TabExecutor
so I have the command /ft and theres like 6 sub arguments to it
perfect
implement TabExecutor instead of CommandExecutor
as I understand correctly, this line is editing a specific attribute, right?
entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(someDouble));
this is not javascript
What else do I need to change for the existing command?
Nothing, it will make you add an unimplemented method which you add your logic to for tabs
ok ty
its editing the max health specifically as I sent it. there are different Attributes in the enum you can change tho
Hi!
If i have a permission maxamount.1, how can I get the number without knowing what numbers you can be faced to?
Thanks
my point is that my entity probably doesn't have any attributes so i can't edit them, i will send the code in a moment
what entity were you editing again?
I register custom
protected int getEffectivePermIntNode(String playerName, String node) {
/*
* Bukkit doesn't support non boolean nodes
* so treat the same as bPerms
*/
Player player = BukkitTools.getPlayer(playerName);
int biggest = -1;
for (PermissionAttachmentInfo test : player.getEffectivePermissions()) {
if (test.getPermission().startsWith(node + ".")) {
String[] split = test.getPermission().split("\\.");
try {
int i = Integer.parseInt(split[split.length - 1]);
biggest = Math.max(biggest, i);
} catch (NumberFormatException e) {
}
}
}
return biggest;
}```
modify for yoru use
looking at the code youre making a completely new entity type... i cant really help you with that. I thought you were trying to modify like a spider
or am I reading this wrong
correct
thanks
how would I add an autocomplete of all online players for a specific one of these commands?
return null
what? No, I mean I want the autocomplete of a specific list for args[0] and if args[0] is "transfer" i want it to give an autocomplete list for args[1] of all online players
if (args.length == 1) return null;
Bruh it doesn't work
if (player.getItemInHand().getType() == Material.WOODEN_AXE) {
if (player.getGameMode() != GameMode.CREATIVE) return;
if (!player.hasPermission("ee.loc")) return;
if (event.getAction() == Action.LEFT_CLICK_BLOCK) {
playerManager.setPlayerLocation1(player, event.getClickedBlock().getLocation());
player.sendMessage(MaxiCity.chat("&aPosition 1 set!"));
} else if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
playerManager.setPlayerLocation2(player, event.getClickedBlock().getLocation());
player.sendMessage(MaxiCity.chat("&aPosition 2 set!"));
}
}
why it doesn't work?
error?
there's no error
maybe the issue is this?
(player.getItemInHand().getType() == Material.WOODEN_AXE)?
Bukkit.getOfflinePlayer(setX.getString("owner")).getName();
Why does this call take 2 seconds?!?!?!?
If you have alot of unique joins it checks all of them.
Plus you're using setX.getString("") so it has to get the string every time too.
ah okay, but i am on my own server where 2 people have joined in total xd
then most likely the second option
Is your server lagging then?
IDK then. You timed it and it took 2 seconds or did another point in your code take 2 seconds?
i removed it and it was instant
Yeah IDK then Try looking through the source code.
if the player hasnt joined it has to ask mojang for their uuid
thats why the method is deprecated, it says this in the docs
the player is me xd
what is it replaced by?
use uuid not name
I thought it only gets players that have joined the server
it is for outputting the owners name
isnt getString(owner) their name?
no, i store the uuid
uuid as a string?
but thats what I was using until now
I have the command "/challenge start" to run a function.
After someone ran it manually once, it should always run by itself at server start.
I guess for this to be possible, i have to save in a file, if someone ran the command. Right?
Whats the best way to do this? Make a config? Make a yml file? make a text file and at server start check if it exists? or is there any easier way to do it?
where can i find download for bungeecord.jar for 1.17+
if somebody does it, save the default config.
on startup check, if the config exists, if yes, then execute the md
do you know where can i find download for bungeecord.jar for 1.17+
latest bungeecord download -.-
ah, so just use the config file as a boolean?
Exists -> run function
Doesnt exist -> dont run funciton
yup
not a bad idea, thanks
Anyone know how I can detect if someone tries to force op?
does that even still work in 1.17 ?
you can check the command-sender, and if its console its probably forceop
unless you op people via console
I don't understand
^
Forceop from hacked clients was patched long ago
area:
description: Manages areas
usage: /area <new:remove:set:add:info> <name> [<owner:coowner>] [<player>]
permission: ee.area
permission-message: &cYou do not have permission to execute this command!
Did you set up a tab completer
They still aren't
no, how do you setup a tab completer?
implements tabCompleter
forceop as i know it always uses an exploit to make the console run the op command. so yeah, probably the only way to check if the console runs the command
in my command class?
yes
Just check if console runts the op command and then if it does then ban the person that was opped
I'm almost certain no force op exploit exists on online 1.17 servers
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
List<String> lis = new java.util.ArrayList<>(Collections.emptyList());
lis.add("help");
lis.add("create");
lis.add("bind");
lis.add("unbind");
lis.add("delete");
lis.add("lock");
lis.add("transfer");
lis.add("info");
return lis;
}
same
like that ^^
You can use Lambdas
there are many
Show me one
getCommand("yourcommand").setTabCompleter((commandSender, command, s, args) -> {
if (args.length == 1) return ...
else return ...
});
the simplest one would be an injected plugin
bungeecord exploits
iirc there was one with mojangs authentication servers
That isn't what I was talking about though
exploits never dont exist
I specifically said hacked clients, not backdoored plugins
still not impossible
yeah such a thing has never existed
There was one
you werent even the one asking the question
With written books / signs
yeah but not the console executed the command
the player clicked did
How do I add a different TabComplete list for each argument, depending on the previous argument? Like a tree
For some reason registering commands via the command map doesn't really work 100% 🤔
check the arguments
Check the length of the args array
The command still runs but tab completion is weird
exactly that, a tree
where do I check them -.-
ofc it did, 1.8.5
inside your onTabComplete method 🤔
ok ty
String[] args doesnt exist for nothing
alr ty
getCommand("yourcommand").setTabCompleter((commandSender, command, s, args) -> {
if (args.length == 1) return Arrays.asList("firstcompletion", "firstcompletionalternative");
else if (args.length == 2) return Arrays.asList("secondcompletion", "secondcompletionalternative");
else return Collections.emptyList();
});
Tree. thats how.
Does anyone know what I did wrong?
https://github.com/IllusionTheDev/SkyblockCore/blob/master/src/main/java/me/illusion/skyblockcore/spigot/command/impl/OldCommandManager.java - Where I register my custom commands, on the command map
https://github.com/IllusionTheDev/SkyblockCore/blob/master/src/main/java/me/illusion/skyblockcore/spigot/command/BaseCommand.java - The command class itself
Running the command with args works, but if I don't set any args, it gives me an unknown command
you method makes no sense
My comparisonresult classes handle args but that's about it, I left the base command to be completed by bukkit, as registering a command via plugin.yml + getCommand method handles label completion
🤔
it does
TabCompleter is an interface
But yeah, just use lambdas, way simpler
else return Arrays.asList(new String[]{}); daily reminder to use Collections.emptyList()
Ah, that's how, i was wondering, thank you!!
Daily reminder varargs is a thing
whats that
instead of Arrays.asList(new String[] {""}); -> Arrays.asList("string", "string2");
sure it does
Guess I'll go screw myself over my oddly specific issue
Also you may re-use those lists
Make a constants instead of creating new lists everytime
idk if its worth that liiiiittle performance boost to write more code
its not imo,
but still a good point, yeah, could do that
Just use a command framework smh
command frameworks are completely unnecessary
it is smh
But be careful
performance boost.. hm, you just dont want to create new objects on every tabcompletion
you don't want to end up like CMI which is leaking and crashing my server due to tab completion caching
Would my AutoCompletion work here?
https://pastebin.com/aHdiGwhd
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
I hate your code lmao
I like to strive for clean code but I look at my code and it isn't beginner friendly
show us your code
Why do you use Collections.emptyList if you're creating a new array list?
Why not use a switch-statement instead of all those
if ( ... equalsignorecase ...)
he got it from my code i think, so blame and teach me
lombok
Ok same question then xD
oh wow I used lombok to avoid pressing alt+insert 25 times and have 500 lines of code at the bottom of a class that no one will look at
Teach yourself
I tried and this is what I came up with. it works. if somebody has a problem with it, I ask them to teach me their method and tell me why theirs is supposedly better
Just use new ArrayList<>() lol
alright, thanks
?
?!?
it works fine lol
???
true xD
???
didnt see that implements
lmao shitStorm incoming
if it works fine, where is the problem? xD
floskater99.add(new ShitStorm)
it doesn't work
it does
:D
no what I did doesn't work
did you register the tabcompleter
do args.length == 1 instead of args.length == 0
cuz it somehow starts at 1
idk why
?
oops

well my class implements it
doesnt matter
why?
max
do args.length == 1 instead of args.length == 0
getCommand("antiac").setExecutor(new AntiACCommand(this));
getCommand("antiac").setTabCompleter(new AntiACCommandTabCompleter());
you have to set the tabcompleter explicity to the command
it doesn't
if you implement TabExecutor, you only register teh command as normal
sure, but args.length is never 0
it is if the array is empty
args length of 0 would be an empty args
bruh that's shit code if you have 10 commands then you would need 20 classes
sure that it will find the tabcompleter?
oh wait misread
tabexecutor
you can also just use the TabExecutor like Elgar said
just use lambdas
ok
public class AreaCommand implements TabExecutor
and I don't have to do this getCommand("antiac").setTabCompleter(new AntiACCommandTabCompleter());
nope you dont have to
in the onTabComplete method you can then just check " if (command.equalsIgnoreCase(...)) ... " for every command
i assume. im pretty new, sorry if thats wrong xD
no need, the tab completer will only trigger for teh command its registered with
but he doesnt register it
^
you only need to register the command
he wants to have a lot of commands
if you implement TabExecutor, or TabCompleter in teh command class
How can I make an array of string lists, and initialize it?
Thats how i'm trying right now:
List<String>[] suggestions = new ArrayList<String>()[]{Arrays.asList("start","stop"), Collections.emptyList()};
how do you add the stuff to the pom.xml im not used to maven lol
i tried this
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.tristandasavage</groupId>
<artifactId>Cool Minigames</artifactId>
<version>1.0</version>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<repositories>
<!-- This adds the Spigot Maven repository to the build -->
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<!--This adds the Spigot API artifact to the build -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.17.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
but it doesnt seem to work
I mean why not just a List<List<E>> but even that is rarely the right design
What does not work?
Have you reloaded your project?
but when i try to install it it doesnt work
oh
wait i have to restart my ide first
alrighty
How do you set blocks at certain locations to turn into air?
setType
an example?
@foggy estuary
i use Intelij 😄
Very good
how to delete the config file?
I can use saveDefaultConfig() to create it, but there is no deleteDefaultConfig()
why would you want to delete it
because i use it as a boolean
if config exists i run a function at serverstart, if not then not
i dont get the point but anyways, you need to get the File and then #delete it
not planning on saving anything in it atm, just need to save that one byte, so i thought i just use the config itself to do so
how do i get the file
File file = new File(path, name);
doesnt that create a new file
ok, so only run that code if config exists
how do i check if config exists? getDefaultConfig == null ?
file.exists
ah so it doesnt create the file
"it represents the file"
i see
ok, ty, ill try it