#help-development
1 messages · Page 2019 of 1
HashMap<UUID, Long> cooldown = new HashMap<>();
if(cooldown.containsKey(sender.getName())) {
int cooldownTime = 30;
long timeLeft = (cooldown.get(p.getUniqueId()) + cooldownTime) - System.currentTimeMillis();
if(timeLeft>0) {
sender.sendMessage(ChatColor.RED + "Your on cooldown for " + timeLeft + " seconds!");
return true;
}
}
cooldown.remove(p.getUniqueId());
cooldown.put(p.getUniqueId(), System.currentTimeMillis());
``` made the code more readable but im still having the same issue
wdym
in what case
like if you type
/hello
it says hello (username) petar
like
hello Skygamez
is there a way to get the players username
sender.sendmessage("Hello " + sender.getName);
limit command use based on username?
yes
like lets say u can only type it
once
and then have to wait until someone else types
Put the latest executor uuid into a variable
no clue how
like this is what I got so far
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class HelloCommand implements CommandExecutor{
static int playerCount = 0;
public HelloCommand(Main plugin) {
plugin.getCommand("hello").setExecutor(this);
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if(!(sender instanceof Player)) {
sender.sendMessage("Only players may execute this command!");
return true;
}
Player p = (Player) sender;
playerCount++;
p.sendMessage("Hi!");
Bukkit.broadcastMessage(sender.getName() + " has joined sumo | Player Count: " + playerCount +"/2");
return true;
}
```
and I dont want someone to be able to join more than once
but currently they can
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (sender.getName() != "petarpotato") {
sender.sendMessage("You are not allowed to run this command!");
return true;
}
someLogicHere();
return true;
}```
but then they cant type it the first time around
what do you mean
When player runs command, set variable to player uuid
I only want it to allow you to do the command once
how would I go about doing that
Also, when player runs command check that the last uuid is either null or not their uuid
Cast sender to player (after checking) and use getUniqueID
umm, how would I cast a sender to player and then getUniqueId
sry I am really new to developing on minecraft
new question that will solve all old questions
how do I store the players name
can I just make an array of strings
and store name in it?
Sure
aright
for now, I think that might be to advanced, I have no idea what that stuff is, but still thanks though for explaining thought process
is there any way to make a item stored in an itemstack wearable?
bump
PlayerPickupItemEvent is deprecated i think
Yea I know but it makes sense in my case
hmm
guys does anyone know how I would make multiple comands in one plugin
this is what I got so far
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
public class HelloCommand implements CommandExecutor{
static int playerCount = 0;
static ArrayList<String> array = new ArrayList<String>();
public HelloCommand(Main plugin) {
plugin.getCommand("hello").setExecutor(this);
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if(!(sender instanceof Player)) {
sender.sendMessage("Only players may execute this command!");
return true;
}
boolean canUJoin = true;
for(int i = 0; i < array.size(); i++) {
if(array.get(i).equals(sender.getName())) {
canUJoin = false;
}
}
if(canUJoin) {
Player p = (Player) sender;
playerCount++;
Bukkit.broadcastMessage(sender.getName() + " has joined sumo | Player Count: " + playerCount +"/2");
array.add(sender.getName());
}
return true;
}
}```
and it happens when you type hello
put the onCommand in a separate class
eek, explain plz
i understand how to make a diffrent class and all
public class CommandClass implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if(!(sender instanceof Player)) {
sender.sendMessage("Only players may execute this command!");
return true;
}
boolean canUJoin = true;
for(int i = 0; i < array.size(); i++) {
if(array.get(i).equals(sender.getName())) {
canUJoin = false;
}
}
if(canUJoin) {
Player p = (Player) sender;
playerCount++;
Bukkit.broadcastMessage(sender.getName() + " has joined sumo | Player Count: " + playerCount +"/2");
array.add(sender.getName());
}
return true;
}
}```
plugin.getCommand("hello").setExecutor(new CommandClass());
?
make a new class
and put your onCommand function in it
make sure the class implements commandexecutor tho
then go to your onEnable() in your main class
and replace the command executor line with java plugin.getCommand("hello").setExecutor(new YourClassName());
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin{
@Override
public void onEnable() {
new HelloCommand(this);
}
}
?
replace new HelloCommand with
plugin.getCommand("hello").setExecutor(new HelloCommand(this));```
but how would that make it so that a player can type multiple comands in same plugin
yeah
but change "helloi"
however change HelloCommand to your new class
to soemthing elkse
yeah
why do I need this
plugin.getCommand("hello").setExecutor(new HelloCommand(this));
instead of
what I had before
new HelloCommand(this);
ohhh is it because the "hello" and the "other thing" is diffrent
that tells the server that when you do /hello to execute the code from HelloCommand
aright
otherwise it will throw an error on enable
is there any way to make a item stored in an itemstack wearable?
would it be like
commands:
hello:
unjoin:
oh also, it says there is no "plugin" defined in my Main
show main class and plugin.yml
instead of plugin.getCommand("hello").setExecutor(new HelloCommand(this));
do this.getCommand("hello").setExecutor(new HelloCommand(this));
and no
oh okay
???
you have to do
commands:
hello:
description: something description
unjoin:
description: something description```
no you dojnt
do u need discibtopn
who told you that
no
oh
this works
oh ok
not for me
it does
odd
What would I do if I wanted to make it so that only the player that dropped the item can pick it up? As in I dont want other players picking up other people's items.
check if the person thats picking it up is the same person that dropped it
if not
cancel the event
But I cant figure out how to check who dropped it
ig you could detect for when the item is dropped and then store a hashmap variable for the item and who dropped it
then when an item is picked up compare the person who dropped it to the person who picked it up
I was thinking about that
nothing works, ._.
commands no longer work
does anyone know why this code no work ._.
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin{
@Override
public void onEnable() {
this.getCommand("join").setExecutor(new HelloCommand(this));
this.getCommand("leave").setExecutor(new UnJoin(this));
}
}
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
public class HelloCommand implements CommandExecutor{
static int playerCount = 0;
static ArrayList<String> array = new ArrayList<String>();
public HelloCommand(Main plugin) {
plugin.getCommand("join").setExecutor(this);
}
public HelloCommand() {
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if(!(sender instanceof Player)) {
sender.sendMessage("Only players may execute this command!");
return true;
}
boolean canUJoin = true;
for(int i = 0; i < array.size(); i++) {
if(array.get(i).equals(sender.getName())) {
canUJoin = false;
}
}
if(canUJoin) {
Player p = (Player) sender;
playerCount++;
Bukkit.broadcastMessage(sender.getName() + " has joined sumo | Player Count: " + playerCount +"/2");
array.add(sender.getName());
}
return true;
}
public ArrayList<String> getPlayers(){
return array;
}
public void lousePlayer(){
playerCount--;
}
}```
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
public class UnJoin implements CommandExecutor{
static int playerCount = 0;
static ArrayList<String> array = new ArrayList<String>();
public UnJoin(Main plugin) {
plugin.getCommand("leave").setExecutor(this);
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
HelloCommand data = new HelloCommand();
ArrayList<String> array = data.getPlayers();
boolean isPlayerThere = false;
for(int i = 0; i < array.size(); i++) {
if(sender.getName().equals(array.get(i))) {
isPlayerThere = true;
}
}
if(isPlayerThere == true) {
data.lousePlayer();
}
else {
sender.sendMessage("You Must Join To Leave!");
}
return true;
}
}```
cant do any commands >_<
You need to return true at the end here
Show your plugin.yml
And did you get any errors in console
name: MyPlugin
version: 1.0
main: org.potatocode.Main
commands:
join:
leave:
I dont think so, let me check
Try putting a description
commands:
join:
description: some description
Also you have HelloCommand defined twice
explain
public HelloCommand(Main plugin) {
plugin.getCommand("join").setExecutor(this);
}
public HelloCommand() {
}
that is because I needed an overloaded constructor
in my UnJoin.java
so I could access some variables
without having to create stuff
or run the other stuff
You don’t need the second hello command
does anyone know how i could change a player's nametag?
And you don’t need to define the join command outside of the main class
Make the variables you want to be accessed from other classes static
oh yeah totaly forgot, they are static
but they are already public
so I dont need acessors or setters
where
public means is that it can be accessed if the class is instantiated
if a variable is private it cant be accessed outside of the class at all
you dont need to do plugin.getCommand("join").setExecutor(this); in a class that isnt the main class
Could not load 'plugins/HelloWorld.jar' in folder 'plugins'
thats what it says in logs
do you have duplicate jars?
no
hmm
I have not tried the discibtion thing one sec
check your plugin folder and closely check to make sure you do not have a duplicate jar
100% sure dont have dulipcate
you should check then
what is stacktrace?
?
wait
U ARE A GENIUS
it worked the diciption
I changed that and it worked
it could have been something else
but it worke
d
huh
whats diciption
description?
yeah
👍
Can I force the hashmap to add a new value instead of overriding a different one? I want to have multiple with the same UUID
You want two exactly the same keys?
UUID and use list as value?
Yea hearing that from another person makes me feel dumb
Nevermind
is it possible for me to use skullMeta to get a skull like so:
https://minecraft-heads.com/custom-heads/decoration/2970-chest
does anyone know how to tp the player into a specific x and y coordinante when they type the command
just x and y?
or do you mean XYZ
use Location, also make sure to search up things before you ask questions here @lime jolt
oh wait sry my question was worded terribly
how do I make it so that they cant move from that position
like they are sutck
stuck
or, I will just spam teliport them
you can teleport them to their old location in the player move event
okokok
also does anyone know what the term is used for display something to someones screen
like a hello message
but not in the chat
or cancel the player move event
event.SetCancelled(true)
and on there screen
oh okay
yw lol
like a title?
oh a title?
if thats what it is called
#setCancelled (no uppercase s)
title is big text in middle of screen
yes do Player#sendTitle(title, subtitle, fadeIn, stay, fadeOut)
title and subtitle is a string
and the 3 numbers are integers
in ticks
so if u put 20 for stay it wil stay for a second
aright thanks
for Player
can I add the username instead/
thats the instance of the player
no not username
the instance of the Player object
is there any way to make it go to a specific username
for what reason?
yea Bukkit#getPlayer(String name)
where do u want to send the title in?
an event?
an event I think
ur using 1.8?
if ur sending it in an event just use e.getplayer
which event
so would it be Bukkit#getPlayer(String name)#sendTitle(title, subtitle, fadeIn, stay, fadeOut)
what event
are u using
wanna set it to that
idk ;-;
no check if the player doesn't exist first null checks are important
then use SkullMeta
SkullMeta doesnt support that?
I already check
how do you not know what event?
sec, i might have a method for you
idk I am new to this stuff started like 5 hours ago
where
in the event handler you made?
if an event is the trigger your the one who specified the event
umm, okay I dont think it is an event
a command maybe
command
yes
essentialy 2 people are typing a comand
that queues them in game
and now I am making count down
in that case it'd be if sender instance of player logic
appear on only there screen
do you have a CommandSender object?
public static ItemStack setSkullOwnerNMS(ItemStack is, String url) {
return setSkullOwnerNMS(is, url, UUID.randomUUID());
}
public static ItemStack setSkullOwnerNMS(ItemStack is, String url, UUID uuid) {
try {
byte[] decodedBytes = Base64.getDecoder().decode(url.getBytes(StandardCharsets.UTF_8));
String decoded = new String(decodedBytes).replace("{\"textures\":{\"SKIN\":{\"url\":\"", "").replace("\"}}}", "");
SkullMeta headMeta = (SkullMeta) is.getItemMeta();
GameProfile profile = new GameProfile(uuid, null);
byte[] encodedData = Base64.getEncoder().encode(String.format("{textures:{SKIN:{url:\"%s\"}}}", decoded).getBytes());
profile.getProperties().put("textures", new Property("textures", new String(encodedData)));
Field profileField;
try {
profileField = headMeta.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
profileField.set(headMeta, profile);
} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
is.setItemMeta(headMeta);
} catch (Exception ex) {
ex.printStackTrace();
}
return is;
}
so you want the sender and then the first argument
i'd make something to mange your queues in that case
./testcommand (player)
I have that
I store all my players
in a string of arrays
array of strings
I have the usernames
@quaint mantle this will take the value in section 'Other, Value:' as input
why would u do string?
all playes?
why
store UUID if anything
though storing every player online is a bit much
strings are all I know
how would I use Player objects
how would I store it
you dont
no
?!?!?!
dont store player objects
don't store players lol
only in very specific scenerio's you can
I am storining there names in a string
not this case
you shouldn't even store every player on your server in strings
yes
if you want to remember a player use their uuid
yes?!?!?!?
always use Player object never use string
GameProfile doesnt exist, and Property doesnt either
yes do Player[]
what are you trying to do? that stuff is not needed anymore
uuid
alright thanks, ima try all of this stuff out
you can access textures etc with API
This was for me
idk how to use that
okay so what are you trying to do? 😄
ima just try making an array of Player
Turn this into a PlayerSkull https://minecraft-heads.com/custom-heads/decoration/2970-chest
player doccumentation on spigot
uuid only for storage
by getting its NBT tag data
ok
player is fine for a temporary queue
alright
SkullMeta#setPlayerProfile
{
"function": "set_nbt",
"tag": "{display:{Name:"Chest"},SkullOwner:{Id:"f565f047-aef7-436c-b0d6-5b7e95edd8e4",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGNkM2M0NWQ3YjgzODRlOGExOTYzZTRkYTBhZTZiMmRhZWIyYTNlOTdhYzdhMjhmOWViM2QzOTU5NzI1Nzk5ZiJ9fX0="}]}}}"
}
Its not a profile however
Its a URL that generates it
You can easily make a skull from the texture url with the PlayerProfile API
you can clone profiles and then set their textures from the URL
Ill see
why would you store the object itself if you could just store the identifier?
what you always should do
but anyway, here's my SkullUtils class: https://github.com/JEFF-Media-GbR/JeffLib/blob/master/core/src/main/java/de/jeff_media/jefflib/SkullUtils.java
my code takes the base64 encoded data and creates a skull out of it. but this indeed was for 1.8
Yes
if sender is a Player, sure
alright thanks
you probably want to check instanceof first
Assuming the sender is a player
indeed they will be, thanks for all the help
Is it bad practice to use a Boolean for something that isn’t true/false
Like day/night
i tend to use enums
Figured enums would be better
i would say so. an enum would be much cleaner and more understandable
GameProfile is part of NMS
NMS?
NotNull is a jetbrains annotation
you should just use the new PlayerProfile stuff instead
you need to run buildtools and depend on that
I mean technically it’s not NMS, but it’s part of the raw server
then you don't have to mess with NMS stuff
yep it's part of com.mojang.authlib
and one would have to manually install it to the maven repo
but for recent versions i recommend looking at mfnalex's skullutils
Did he update it to not be legacy
my SkullUtils uses the GameProfile things
I only discovered the PlayerProfile API 2 hours ago
TL;DR you’ll want to use Bukkit.create(Player?)Profile and PlayerProfile.setTexture
(however my SkullUtils also has methods to set skull blocks into the world so it'd be useless to change to the API methods anway, since I still need GameProfiles ayway)
The profile API works for skulls too
The home of Spigot a high performance, no lag customized CraftBukkit Minecraft server API, and BungeeCord, the cloud server proxy.
Wdym run buildtools
read dis
For the version you are using
oh awesome
buuut
does anyone know what "yaw" and "pitch" are in positioning
yes
there's still need for my "legacy" way: which is base64 textures
Why’s that
why do I need them
You’ll never guess what that base64 decodes too
its where they are looking
yaw = left/right, pitch = up/down
coooool
head goes ⬆️ ⬇️ ⬅️ ➡️
so by what does it go up by
(It’s a url)
like is 1 = 1 pixel
wdym? the URLs aren't just the base64 string
Okay but where do I put buildtools.
in any folder
doesn't matter
Okay..
run it
Send me a head base64 string
i got it on my desktop in a folder for example
:(
boons!
:(
im a man of my word
its only for this server
does anyone know why this is getting mad at me
Location loc = new Location(Bukkit.getWorld("world"), -16.5, 67, -22.5, 0, 0);
oh ok
Gotta parse it a bit but that’s fine
?notworking
"Does not working" is a useless statement. Please describe what exactly is not working, what you expect it to do, and what actually happens. If you get any console errors, also ?paste the entire stacktrace.
people who have buildtools on their desktop
says Cannot instantiate the type DocumentationTool.Location
Ugh I have to compile something that uses Lombok
where's the problem
do u know where I can find the correct import for it
I have to install Lombok
yes, in org.bukkit
Gross
huhu no
he just told you
you don't have to install anything
Any website that shows block data if its orientable or implements directional
if it's in the pom.xml, just do "mvn install" and done
org.bukkit.Location
lombok does not require anything to be installed
but where can u see all the imports
i mean most people just know
?jd
i see
My IDE doesn’t support it from maven
Eclipse
eclipse 100% supports it
the example video on the lombok website was made in eclipse
lombok also works fine without any IDE
sometimes people think lombok hacks into the IDE or similar, but that's just not true, lombok is awesome and works just fine directly with javac :3
How
Surly it must do something so the IDE recognizes the methods that don’t exist before compiling
pretty sure the ide just adds support for lombok
yeah that's normal annotation processing
not the other way arround
I wanted to say - lombok does not REQUIRE any intellij plugins so that it compiles
but sure, intelliJ must process the lombo annotations to understand there are the generated methods
but even if you wouldn't have any lombok plugin, it would compile from within intellij
Huh
or whereever
Guess I need to stop huffing gas
lol
lombok is awesome just because of the logo
?bt
I read the site.
It doesnt tell me how to install it on the plugin
Oh FFS
you have no idea what buildtools is, right?
as your dependency
0 Clue.
it builds the spigot etc source code and .jar files for you
Spigot->Spigot-API->target
in the buildtools directory
a signature?
what signature?
Okay found the jar, as a dependancy?
In my plugin or
@earnest forum implimentation or compileOnly
what does that mean
compileOnly
what ide are u using
it's the gradle equivalent to maven's <scope>
compileOnly 'spigot-api-1.18.1-R0.1-SNAPSHOT-shaded'
thx
compileOnly = provided
while implementation basically means <scope>compile</scope>
so it also gets shaded
It states that its an invalid module notation
Was I suppost to place the file somewhere?
Make sure you're using Java16 JDK in your PATH.
Compile main-project without signature by using debug profile: mvn install -Pdebug
no, that doesn't even make sense
no idea what that means lol
you have to add com.mojang.authlib to your dependencies
how do I do that
just add it manually again
as an implementation
or
I have no idea about gradle
in maven it works like this:
<dependency>
<groupId>com.mojang</groupId>
<artifactId>authlib</artifactId>
<version>3.2.38</version>
<scope>provided</scope>
</dependency>
but gradle, no idea
It's using the maven-jarsigner-plugin
If the jar isn't signed it won't run without a JVM argument
And the server I am doing it for has a shitty host that doesn't allow custom JVM args
does a tag for terracotta blocks exist
oooh
I have no idea about that
I have never signed any .jar files
They pushed an update for 1.18.2 a week ago, it's not on SpigotMc, it's not on BukkitDev
Their jenkins is a 404
And I can't compile it locally
hm let me see
i think there does not
Aight imma make an enum for it instead
Just make an EnumSet
declaration: package: org.bukkit, interface: Tag
added only in 1.18?
no idea
My spigot jar is 1.17.1 rn
Appreciate yall
Nope no terracotta tag on 1.17
Aight thanks, imma make an enum for it along side other blocks that implements directional, bisected or orientable
@tender shard figured it out lol
compileOnly 'org.spigotmc:spigot-api:1.18.1-R0.1-SNAPSHOT-shaded'
had to search here
for the correct repo
@tender shard question: is maven better than gradle?
starting to see more ppl using maven than gradle
i've seen more people switch to gradle than use maven
Honestly I'd say its preference
^
Gradle can do more though apparently, which is why paper moved to it
Gradle is more complicated, but it's less verbose and more powerful
But I doubt you have to worry about that for a plugin
I do enjoy not having my dependencies be like 7 lines each though 
compileOnly 'com.mojang:authlib:1.5.21'
am I compiling this right?
Its not working
*i cant access com.mojang.authlib
?notworking
"Does not working" is a useless statement. Please describe what exactly is not working, what you expect it to do, and what actually happens. If you get any console errors, also ?paste the entire stacktrace.
Refresh gradle
I legit just stated what was wrong
k
@hasty prawn nothing
nvm
maven {
url = 'https://libraries.minecraft.net/'
}
Appears to be the repo for authlib
no
both are equally good
imho gradle is way more complicated
both can do the same things
I prefer gradle for the less verbose build file
But I agree that it can be a bit complex to use
And documentation is pain to find
yeah gradle files are shorter, but also much more complicated to read etc
but as said, both are totally fine and neither is better than the other
it's like BMW vs Mercedes or Canon vs Nikon or Ubuntu vs Debian etc etc etc
if(event.getRightClicked().getType().equals(EntityType.VILLAGER)){
e.setCancelled(true);
}
this should disable villager trading right?
what event is it?
PlayerInteractAtEntityEvent
yeah that should work
but you should rather use == instead of equals()
Yep I do that
I use the PlayerInteractEntityEvent tho
Idk if it makes a difference
implementation 'de.jeff_media:JeffLib:7.7.0-20220309.181717-13@jar'
Any reason why this dependancy may not load?
I already checked and have no idea. they seem to be using the correct repository, etc. here's the full link https://hub.jeff-media.com/nexus/#browse/browse:jeff-media-public:de%2Fjeff_media%2FJeffLib%2F7.7.0-SNAPSHOT%2F7.7.0-20220309.181717-13%2FJeffLib-7.7.0-20220309.181717-13.jar
Nexus Repository Manager
add some messages
one message above your if statement, and one inside
to see if that code actually runs and if yes, whether the if statement returns true
is it registered
^
just because it is registered doesn't mean it'll run in this case
for example, it might be the wrong event
that's true but I have spent half of a night debugging to figure out why something wasnt running
and it just wasnt registered
oooh sorry I misread
I thought you wrote "it is registered"
and not "is it registered"
Event working and I registered it. but its not canceling
so you have added debug messages?
and those get printed?
Yes
try using the parent class PlayerInteractEntityEvent
everytime you right click a villager?
well but they said their debug lines were printed so that wouldnt change anything
Event is working
true, but there's this note Note that the client may sometimes spuriously send this packet in addition to PlayerInteractEntityEvent. Users are advised to listen to this (parent) class unless specifically required.
alr
yes but since they said their debug message was printed, it must be the correct event
oh yes. its working now
true but maybe something is wrong and you cant cancel from the child
then your debug messages couldn't have been printed.......
that's a problem for md_5 someday then, can't cancel event from InteractEntityAt whatever it's caleld
PlayerInteractAtEntityEvent
I have just checked
right clicking a villager does NOT call the child event
so the statement that you have added debug messages and they were printed cannot be true
wait
right clicking a villager does NOT call PlayerInteractatEntityEvent
Have we determined which is the child finally
Woo we have
The At version is for armorstands btw
the child event says Represents an event that is called when a player right clicks an entity that also contains the location where the entity was clicked., I'd still never use it and just do e.getRightClicked().getLocation();
No no
yes yes I would
oh that's very niche
Used for armorstands since they have different functions depending on what part you click
I am not sure why the API docs were confusing, was pretty straight forward
hey, how is it going. I am back with more questions XD. I am trying to add to a list of strings from config string list, but it keeps giving me, what looks like, a null error??
?paste
also, are you sure the data you are trying to get from the config is indeed of a list type?
show your code
then your list is null
yaml has a specific requirement in how it must be formatted for it to be consided a list
alright, then its something with your code
noone can help if you don't show your code
give them time
I dropped the whole main script in the hastebin
yes, my code is smelly, please no hate
hit the save button and then give updated link
send the full stacktrace too pls
no idea what that is
the error message
the error doesn't come from the code you sent
Any reason why this dependancy wont load?
implementation 'de.jeff_media:JeffLib:7.7.0-20220307.093638-1'
This is the repository:
maven {
name = 'jeff-media-public'
url = 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/'
}
anyway, I can tell you what the problem is: you have an immutablelist, you can't add stuff to it
e.g. if you do stuff like List<String> = getConfig().getStringList("..."), you can't add something to it, as it seems
you'll have to create a new list
at least that's my guess, we gotta see a matching code/error to tell more 🙂
as said, the code you sent can't be the same as the one that caused the error message because the line numbers don't match up
maybe they are using new on a method
according to that unsupportedoperationexception
unless there is a class we are not seeing
they use .add on a list that is immutable
back, the error didn't change, the thing I thought would fix it didn't
you do config.getStringList
that returns an unchangable list
you must do it like this:
List<String> myList = new ArrayList(config.getStringList("..."));
now you can freely manipulate myList
TY!
np
it should be mutable o.O
anyways, that should fix their problem if that is indeed the issue
I really really hope it does fix it
you are all really amazing, and I appreciate you to no end
np 🙂
it didn't do the thing. I did a workaround
@tender shard I figured out how to make the skull!
public static ItemStack getCustomSkull(String url) {
ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
if (url.isEmpty()) return head;
SkullMeta skullMeta = (SkullMeta) head.getItemMeta();
GameProfile profile = new GameProfile(UUID.randomUUID(), null);
profile.getProperties().put("textures", new Property("textures", url));
try {
Method mtd = skullMeta.getClass().getDeclaredMethod("setProfile", GameProfile.class);
mtd.setAccessible(true);
mtd.invoke(skullMeta, profile);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
ex.printStackTrace();
}
head.setItemMeta(skullMeta);
return head;
}
WOOT! Skull!
isn't that basically exactly the method from my lib? 😄
yea but i had to make it into my PluginFuncs thingy
package me.emerald.emeraldsplugin;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;
public class PluginFuncs{
public static void sendGlobalMessage(String msg){
Bukkit.getOnlinePlayers().forEach(sender -> sender.sendMessage(msg));
}
public static ItemStack getCustomSkull(String url) {
ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
if (url.isEmpty()) return head;
SkullMeta skullMeta = (SkullMeta) head.getItemMeta();
GameProfile profile = new GameProfile(UUID.randomUUID(), null);
profile.getProperties().put("textures", new Property("textures", url));
try {
Method mtd = skullMeta.getClass().getDeclaredMethod("setProfile", GameProfile.class);
mtd.setAccessible(true);
mtd.invoke(skullMeta, profile);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
ex.printStackTrace();
}
head.setItemMeta(skullMeta);
return head;
}
}
- I couldnt load ur lib
sadly
make sure you give credit where it is due 🙂
method is just transferred to a new class
Sure thing lol
i hate codeing
While technically true if this code is on a repo, its not obviously apparent where it came from. It is frowned upon to claim code as your making if you didn't come up with it. In these cases, a simple comment at the top usually suffices of where it came from AKA giving credit where it belongs
I spend a solid 20 minutes wondering why my armor stand was not showing its name. I did textArmorstand.setCustomNameVisible(false);, and not textArmorstand.setCustomNameVisible(true);
I don't care if people borrow code from my projects, but it is always nice for people to attribute credit if they have done so 🙂
yeah I mean he just copy pasted the method so a credit must be given
just my chat is incomplete leading to misconception xD
lol
Does anyone know how I would add a blockbench model onto an entity? I have the resourcepack created by ModelEngine, but I'm not sure how to actually spawn the model
getCommand("specialgive").setExecutor(new SpecialGiveCommand());
getCommand("challenge").setExecutor(new ChallangeCommand());
getCommand("tospawn").setExecutor(new ToSpawnCommand());
getCommand("crates").setExecutor(new CratesCommand());
getCommand("balance").setExecutor(new BalanceCommand());
getCommand("shop").setExecutor(new ShopCommand());
getServer().getPluginManager().registerEvents(new InteractionEvent(), this);
getServer().getPluginManager().registerEvents(new OnPlayerChatEvent(), this);
getServer().getPluginManager().registerEvents(new PlaceBlockEvent(), this);
getServer().getPluginManager().registerEvents(new InvClickEvent(), this);
getServer().getPluginManager().registerEvents(new BreakBlockEvent(), this);
getServer().getPluginManager().registerEvents(new PlayerJoin(), this);
getServer().getPluginManager().registerEvents(new PrepItemCraftEvent(), this);
getServer().getPluginManager().registerEvents(new InteractEntityEvent(), this);
getServer().getPluginManager().registerEvents(new EntityDamage(), this);
Can I make this smaller?
Yeah I was gonna suggest that too
instead of calling getServer().getPluginManager() every time you could just set it to a variable
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new InteractionEvent(), this);
ps?
Set the time to Integer.MAX_VALUE
thanks
does PlayerAnimationEvent run every tick while holding down left click on a block?
And there's only one animation it covers lol
is there a way to check if a player is swinging?
ye
like if im starting a runnable when the player hits a block
im checking if they are still breakin git
?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.
you mean
player click a block
There’s an event for starting to break a block
And there’s one for cancelling and one finishing
So making use of those you can tell when they are breaking a block
which ones cancelling?
Can I add github url to recourse page?
I saw other People doing that
So, no problems?
I guess no
ok
Yeah it even has a spot for it
BlockDamageAbortEvent
How can I change recourse icon?
a the option is small
Hi guys! Need some help with a timer that counts time between block place and pressure plate click. Right now I'm listening for the normal BlockPlaceEvent and then save the current time as an Instant. When the player later presses the pressure plate, the time difference is calculated and shown to the player. My problem is that this server-sided approach makes the timer prone to high ping/notwork lag. I was thinking that this might be solved by listening for client packets instead. Anyone here who can help me?
so
you realize listening to client packets is the same right?
you will have the same latency issues
Yeah I was thinking that too, but I've heard rumours it's possible to bypass/improve it by using packets. Here's what another dev said:
hello, I want to spawn a block right next to a player in the direction where player is looking at
can anyone help with me how to get proper direction
I'm aware of getRelative() method but that won't work in this case
Player#getLocation().getDirection() ?
that will return a vector
how do I get the block though
I think if add x and z with the sign of the direction unit vector coordinates it might work
who said that
A developer on one of the leading training servers
I assume this is for something like speed bridging timing?
ofc it is
Location next = p.getLocation().add(vector.multiply(2));
next.setY(p.getLocation().getY());```
it worked
I'm confused. If you want the most accurate time you'd use the client of course but clients can spoof stuff. Unless you're mentioning when the server receives packets from the client but I can't imagine that you'd get huge differences between that and the events.
^
how do i import javadoc using maven?
no like
i have the javadoc in .m2
but its not loading for some reason
where do i execute that?
the terminal is just running an instance of cmd.exe
(intelliJ user)
Yes, that's what this is for.
We have anticheat for packet spoofing, so that's not an issue. Do you know how I can get the time from the client?
You want the clients stuff? You don't want the clients stuff. You should only use what the server has.
Our problem is that players with network lag/high ping is able to get lower times
lower? I thought the opposite
It's probably because they can queue a bunch of packets and then all at once send them to the server thus giving them a head-start advantage.
you wont get the exact times the client sent smth except you are listening clientside
There is really no good solution besides invalidating anyone who seemingly uses lag to their advantage
closest you can get, like mentioned yesterday, is (packet sent time in ms - ping)
That looks 100% like a server-side issue not client-side
if the client was lagging they would be rubber-banding like mad.
Why are you using block placements?
On these videos our moved-wrongly-threshold and moved-too-quickly-threshold was set to 100/200, so I think rubber-banding was more or less disabled
TPS is also consistently 20 and it only happens for individual players, not the whole server at once
So players are allowed to lag out and the solution for that has been disabled -> ?
No, these values were set to 100/200 because someone else wanted to fix "lag-backs" a while ago. We've set them back to a bit above their default values now
It seems to have improved it, but the issue still persists
what exactly is the issue? the timer going crazy? or is there literally a big advantage?
the time seems to be about right in that video though (18s)? They started at 2s in the video, landed on the pressure plate at 20s. That's 18s?
Yeah the second video is about right, but the first one's not
it started late, but how is that a client problem?
i could imagine that he was lagging at the start and his connection got better while bridging.. but that shouldn't affect it, or?
that looks like the server started the timer at the incorrect block place, server started at around 00:04, he landed at 00:09, that gives the 5 seconds.
are you sure your logic is not broken somewhere?
you may also want to get a client to simulate network lag so you can test yourself
The issue here is even if this is a client issue, the solution cannot be to rely on the client for information. You can use this application to create artificial lag and see for yourself https://www.netlimiter.com/.
Here's my logic inside the BlockPlaceEvent @dire marsh:
@EventHandler
public void onPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
if (BridgeSession.this.player != event.getPlayer()) { return; }
Location location = event.getBlock().getLocation();
placedBlocks.add(location);
boolean inRangeX = ((xMax == xMin || location.getBlockX() > xMin + 2) && location.getBlockX() < xMax - 2);
boolean inRangeY = (location.getBlockY() < yMax);
boolean inRangeZ = (location.getBlockZ() > zMin + 2 && location.getBlockZ() < zMax - 2);
if (!inRangeX || !inRangeY || !inRangeZ) {
event.setCancelled(true);
} else {
BridgeSession.this.blockLoc = location;
if (!count) {
BridgeSession.this.time = BigDecimal.ZERO;
start = Instant.now();
count = true;
replayID = player.getUniqueId() + "_" + Instant.now().toEpochMilli();
ReplayAPI.getInstance().recordReplay(replayID, player, location, player);
}
blocks ++;
if (player.getItemInHand().getAmount() <= 15) {
refill();
}
}
}```
can you put that in a code block
?paste
You could always check for an unnaturally large amount of block place events within a timeframe
three ` then java and 3 at the endd
That would indicate some sort of lag
Thanks. The second video is actually one of the owners DDOSing himself. And yes, since the time is actually quite correct, so that's why I'm not 100% sure if this is related to network or not
Good idea
It's probably a hiccup with the server. If it's not then you've got either a client issue or a plugin issue.
if (BridgeSession.this.player != event.getPlayer()) { return; }
first, this seems sus
We're also recording replays every time a player bridges, and looking at the ones experiencing timer lag, all blocks are instantly placed when the replay starts (using AdvancedReplay)
I'm registering a listener per BridgeSession class
comparing the adress seems fine if it have to be that exact player object
Record the time between block placements and look for sandwiching of when the server receives them.
Will do
There is plenty of network limiting software out there to test with. I'd recommend a lag switch to see if that can duplicate it. If that's not the issue then the plugin/server are the problem here
if anything, I would expect a laggy player to have a disadvantage, as the landing and hitting the pressure plate will have a delay until it reaches the server... at least, that's what I've always experienced when I lag on these sorts of things
It's set to false when the reset() method is called, which is every time a player joins or quits the course, or when the player falls or presses the pressure plate
so every listener is per-player?
Only set to true inside the BlockPlaceEvent
Yes
weird structure
If you think about it in terms of exploiting they would initially lag out the start to place as many blocks as possible without banding-back then turn off whatever is creating the lag thus when they finish it doesn't apply.
Assuming it's someone trying to cheat the system and not general lag
Yeah this is exactly what I've been thinking too
Replaced it with if (!this.player.getUniqueId().equals(player.getUniqueId())) { return; } if that's better
I don't see how it can be cheated like that though, cause surely your code should be detecting the first block they place, then calculating the time between that and activating the pressure plate?
unless the client is ahead on movement, and behind on block placements somehow?
which should just be impossible?
I don't think any players are actively exploiting this, but it happens randomly. And if my plugin detects too low times, players are getting banned for cheating (disabled temporarily cause quite a few were complaining about being false banned for timer lag)
to me it seems they're lagging, they catch up and all the block placements get done, but somehow your code is only detecting the last in that block placement, and thus the time is wrong
Or it's detecting the first block at the same time as the last block since all the packets arrived at the same time
couldn't you just check if they didn't started yet and cancel if so?
I'll have a think about it for a bit
What do you mean by didn't start yet?
Alright, thanks for helping
@carmine pecan can you confirm how many times the code within if(!count) executes after a lagspike like shown in the videos?
I could add some debug code for it, yes. But it might take a while to get any results
yeah that's why I suggest getting something that allows you to reproduce the issue
I have this code:
@EventHandler
public void BlockBreakEvent(BlockBreakEvent e){
Block b = e.getBlock();
Player p = e.getPlayer();
if (!(plugin.blocks.get(p) == null)){
if (b.getType().equals(Material.STONE)){
plugin.blocks.put(p, plugin.blocks.get(p)+1);
EconomyResponse response = economy.depositPlayer(p, 1.0);
}
}else{
if (b.getType().equals(Material.STONE)){
plugin.blocks.put(p, 0);
EconomyResponse response = economy.depositPlayer(p, 1.0);
}
}
if (plugin.getTokenMiner().getInt("Player."+p.getName()) == 0){
Random r = new Random();
Integer rr = r.nextInt(5);
if (rr == 1){
plugin.tokens.put(p, plugin.tokens.get(p)+1);
}
p.sendMessage("1");
}else{
Integer level = plugin.getTokenMiner().getInt("Player."+p.getName());
if (level <= 250){
Random r = new Random();
Integer rr = r.nextInt(TokenMic(level));
if (rr == 1){
plugin.tokens.put(p, plugin.tokens.get(p)+1);
}
p.sendMessage("2");
}else{
plugin.tokens.put(p, plugin.tokens.get(p)+TokenMare(level));
p.sendMessage("3");
}
}
}```
everything works perfectly, just up to ``p.sendMessage("1");`` in .yml file, i have:
```yml
Player:
xSenny_: 1000```
Why it doesn't work?
what do you expect to happen? o0
p.sendMessage("1") is the last statement in your if block
so if this line is true:
if (plugin.getTokenMiner().getInt("Player."+p.getName()) == 0){
then p.sendMessage("1") is the last statement that gets executed
that's the whole idea of if/else
plugin.getTokenMiner().getInt("Player."+p.getName() = 1000
so the plugin need to do:
plugin.tokens.put(p, plugin.tokens.get(p)+TokenMare(level));
p.sendMessage("3");
}``` i guess
cause the plugin.getTokenMiner().getInt("Player."+p.getName() isn't equal with 0, and isn't less or equal with 250
is this right?
?
guys
does anyone know whats wrong with this line
array.get(0).sendTitle("Hello!", "This is a test.", 1, 20, 1);
the arraylist is made of players
and there is a player at array.get(0)
it says
The method sendTitle(String, String) in the type Player is not applicable for the arguments (String, String, int, int, int)
but then how would I fade it out
and do all those other paremiters
That’s why
dãng ok
can some1 help me?
.
"Does not working" is a useless statement. Please describe what exactly is not working, what you expect it to do, and what actually happens. If you get any console errors, also ?paste the entire stacktrace.
i do not have any error
everything works perfectly, just up to p.sendMessage("1");
what exactly were you expecting to happen by using those numbers?
if you were instead wanting to output what is in your config instead
you should fetch the strings from there
Integer TokenMic(Integer level){
int sansa = 0;
if (level <= 50){
sansa = 5;
}else if ((level <= 100) && (level >= 51)){
sansa = 4;
}else if ((level <= 150) && (level >= 101)){
sansa = 3;
}else if ((level <=200) && (level >= 151)){
sansa = 2;
}else if ((level <= 250) && (level >= 201)){
sansa = 1;
}
return sansa;
}
Integer TokenMare(Integer level){
int multi = 10;
if ((level <= 300) && (level >= 251)){
multi = 2;
}else if ((level <= 350)&&(level >= 301)){
multi = 3;
}else if ((level <= 400) && (level >= 351)){
multi = 4;
}else if ((level <= 450) && (level >= 401)){
multi = 5;
}else if ((level <= 500) && (level >= 451)){
multi = 6;
}else if ((level <= 550) && level >= 501){
multi = 7;
}else if ((level <= 600) && (level >= 551)){
multi = 8;
}else if ((level <= 650) && (level >= 601)){
multi = 9;
}else if ((level <= 700) && (level >= 651)){
multi = 10;
}else if ((level <= 750) && (level >= 701)){
multi = 11;
}else if ((level <= 800) && (level >= 751)){
multi = 12;
}else if ((level <= 850)&&(level >= 801)){
multi = 13;
}else if ((level <= 900)&&(level >= 851)){
multi = 14;
}else if ((level <= 950) && (level >= 901)){
multi = 15;
}else if ((level <= 1000)&&(level >= 951)){
multi = 16;
}else if ((level <= 1150)&&(level>= 1001)){
multi = 18;
}else if ((level <= 1300)&&(level >= 1151)){
multi = 20;
}else if ((level <= 1500)&&(level >= 1301)){
multi = 25;
}
return multi;
}```
I see you have a misunderstanding in how strings work.
i put the strings for show you how far the code goes
Testing out Net Limiter now
epic
You have if else blocks
oh dear lord no
Of course only 1 can trigger
so instead of using p.sendMessage("2");
it should be more like p.sendMessage(TokenMare(2).toString());
Why is there a capital letter on the first char of these methods ?
because conventions are not rules or standards of a system
They are standards
They are standards... What could it be so ?
Convention or more better known as style
