#help-development

1 messages ¡ Page 776 of 1

shadow night
#

oh believe me, it's never worth it

chrome beacon
#

Just a waste of time

#

You'd inject in to the netty pipeline

grim hound
grim hound
#

but the write method in the ChannelDuplexHandler

slender elbow
#

LoggingHandler

short shale
#

don't waste your time writing code that already exists unless it's strictly necessary

grim hound
#

is only for the Player that is

chrome beacon
#

why?

#

If you don't want a dependency you can just shade PacketEvents

grim hound
#

cuz it's faster

#

when I do it

chrome beacon
#

No not really

grim hound
chrome beacon
#

Negligable

shadow night
#

in a computational sense your words are complete nonsense

grim hound
grim hound
shadow night
#

one dependency isn't much

rotund ravine
#

Big bois

grim hound
#

Also performance is key to my plugin

#

since it's an antibot

slender elbow
#

online-mode=true is a pretty good antibot

grim hound
#

doesn't matter that literally nobody uses it

short shale
grim hound
shadow night
#

those few nano or miliseconds are not worth it

grim hound
#

there's a major difference between the two

shadow night
#

¯_(ツ)_/¯

grim hound
#

my... my eyes

#

what the

shadow night
#

hell fucking nah, what is that

grim hound
#

yo how do you

#

hide your code

#

at decompilation

#

cuz I was just skidding getting some inspiration

#

and the guy literally said "nuh-uh"

zealous osprey
#

Can you?
Don't you just obfuscate it, too make it hard too understand

grim hound
#

and there are no classes

#

which are responsible

#

for the main logic

shadow night
rotund ravine
#

Obfuscating is a waste of time

grim hound
#

oh wait

#

I found em

sterile token
rotund ravine
#

Some obfuscation even slows down the execution

grim hound
#

mfo thought he could outsmart me

rotund ravine
#

So if ur worried about nanosecond don’g

grim hound
shadow night
#

lol

rotund ravine
#

It is

grim hound
shadow night
#

anticheat obfuscate their code more times than they have lines in their main class where they write all their crap

grim hound
#

how am I even supposed to skid that

shadow night
#

an obfuscator that turns everything into greek would be cool imo

sterile token
#

A good system for those who needs none online players is XCard is a proxy which includes AntiBot, rate-limiting. Its even blocks you directly via firewall if you start spamming packets

rotund ravine
#

Don’t advertise weird stuff

grim hound
sterile token
# grim hound Fuck

you can pretty simple, if you read the bytecode haha. There nothing matters if its obfuscated

sterile token
grim hound
#

for those who needs none online players

#

so like it's over-sensitive?

sterile token
#

what? i dont understand that part im lost

#

let me translate to native lang

rotund ravine
#

Verano is just not the best at english

shadow night
sterile token
shadow night
grim hound
twin venture
#

public String getChestType(Location location) {
return chestLocations.entrySet()
.stream()
.filter(entry -> entry.getValue().contains(location))
.map(Map.Entry::getKey)
.findFirst()
.orElse("default"); // Or another default value indicating no match
}

hi can i do this diffrently?

sterile token
twin venture
sterile token
#

Can just return null too, but yeeah thas okay. Because is more descriptive rather returnning null

twin venture
#

or return the correct value

#

i mean it only return default chest xDD

meager wolf
#

is there a method to "wrap" or \n if line.length>maxLength or should i actually make it ?

pine sandal
#

What are you trying to do with the function?

rotund ravine
#

Lol

#

I asked bing for fun

Hello, this is Bing. I can help you with rewriting your code in different ways. Here are three possible alternatives:

// Alternative 1: Use a for loop instead of a stream
public String getChestType(Location location) {
    for (Map.Entry<String, List<Location>> entry : chestLocations.entrySet()) {
        if (entry.getValue().contains(location)) {
            return entry.getKey();
        }
    }
    return "default"; // Or another default value indicating no match
}

// Alternative 2: Use a lambda expression instead of a method reference
public String getChestType(Location location) {
    return chestLocations.entrySet()
            .stream()
            .filter(entry -> entry.getValue().contains(location))
            .map(entry -> entry.getKey())
            .findFirst()
            .orElse("default"); // Or another default value indicating no match
}

// Alternative 3: Use a ternary operator instead of an optional
public String getChestType(Location location) {
    String chestType = chestLocations.entrySet()
            .stream()
            .filter(entry -> entry.getValue().contains(location))
            .map(Map.Entry::getKey)
            .findFirst()
            .orElse(null);
    return chestType != null ? chestType : "default"; // Or another default value indicating no match
}
#

@twin venture It’s most likely due to you using Location

#

Are you using a proper block location

sterile token
#

when are they fixing legacy compoennts? Im tired of not being able to personalise compoennts via config

chrome beacon
#

fixing?

sterile token
#

Yeah they are broken legacy ones, when you using color codes

thin iris
#

pr it

sterile token
#

It happens that only apply color to some lines, the rest just appears as white

#

not matter if you put a color code before

#

I would like to PR it but i will endup changing the whole shity components api haha

rotund ravine
#

Seems like ur doing smth wrong

#

Is there a jira on this?

sterile token
#

what?

#

Jira is somethign eatable

rotund ravine
#

?jira

undone axleBOT
chrome beacon
#

?jira

undone axleBOT
sterile token
#

what that heck never used it

twin venture
rotund ravine
sterile token
#

i just realize that thing exists sorry i sound rude

rotund ravine
rotund ravine
twin venture
sterile token
rotund ravine
ionic dagger
#

what would be the event or method i would utilize if im interested in making a door that kills a player when they interact with it

rotund ravine
#

I mean if ur locations are based on blocks @twin venture

#

If not you’d want distance

ionic dagger
#

right click

#

open

chrome beacon
#

PlayerInteractEvent

ionic dagger
#

literally

#

im looking at the docs and i skipped that one

#

thats wild

rotund ravine
#

?playerinteractevent

ionic dagger
#

thank you

rotund ravine
#

?interactevent

undone axleBOT
#

The PlayerInteractEvent may be called once per hand. If you only want code to be executed once, you can check the result of https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/player/PlayerInteractEvent.html#getHand(), then decide functionality.

For example, only executing code if the main hand was used:

@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
    if (event.getHand() != EquipmentSlot.HAND) { // * if the hand used is NOT the main hand:
        return; // do not progress past this point  |
    }
    // provide functionality
}
ionic dagger
#

so

#

it would be some sort of

sterile token
#

Could i lag the serve rif im constantly updatin an scoreboard which represents table of current claims depending the current location yo uare

#

Please tag me for any anwers

devout tartan
#

Alright, I understand this isn't a spigot question, but does anyone know how to make a task run before the build task in gradle? SO hasn't helped me
I'm trying this

tasks.getByName("preBuild").dependsOn("ktfmtFormat")

Gradle can't find preBuild task (and neither can it find build task) (getByName fails, other suggested using project.tasks.preBuild, but preBuild isn't a property of tasks either)

sterile token
rotund ravine
sterile token
rotund ravine
#

It doesn’t need to be updated all the time

devout tartan
rotund ravine
#

100ms min should be fine for most things

devout tartan
#

I'm guessing it's not it's correct name (I don't know if this is idiomatic way of getting the main build task)

sterile token
#

oh okay, so what you mean is not updating when he move. Just set a delay of 3 seconds, that perfect right? And again totally thanks!

ionic dagger
#
if (event.getClickedBlock().getType() == Material.OAK_DOOR) {
  event.getPlayer().setHealth(0);
}
rotund ravine
ionic dagger
#

a blocktype?

rotund ravine
#

What do you mean store

sterile token
#

what you trying to do?

#

let star t from there, what you wondering to store

ionic dagger
#

i want to store the block which was interacted with so that i can check it against a door

rotund ravine
#

Why do you need to store it

ionic dagger
#

i dont have to

#

but how do i

#

well

devout tartan
# rotund ravine I can’t recall. Are you doing it in the proper place in the build file?

No idea, this is my build.gradle.kts

plugins {
    kotlin("jvm") version "1.9.10" apply false
    `java-library`
    id("com.ncorti.ktfmt.gradle") version "0.15.1" // https://github.com/cortinico/ktfmt-gradle
}

subprojects {
    tasks.getByName("build").dependsOn("ktfmtFormat") // THIS FAILS

    apply {
        plugin("java-library")
        plugin("org.jetbrains.kotlin.jvm")
        plugin("com.ncorti.ktfmt.gradle")
    }

    ktfmt {
        // KotlinLang style - 4 space indentation - From kotlinlang.org/docs/coding-conventions.html
        kotlinLangStyle()
    }

    repositories {
        mavenCentral()
        maven("https://repo.papermc.io/repository/maven-public/")
        maven("https://plugins.gradle.org/m2/" )
    }

    dependencies {
        compileOnly("org.spigotmc:spigot-api:1.19.3-R0.1-SNAPSHOT")
    }
}
ionic dagger
#

is that code correct? i have tried it i was just thinking through it here

rotund ravine
#

I thhink?

sterile token
#

The code looks fine, but till cant understand what you wondering to store

devout tartan
#

that worked

#

thank you! (Now to figure out ALL Those warnings of unnecesary compilation I have....)

ionic dagger
#

blocktype

#

is there a blocktype variable?

rotund ravine
#

Why do you need to store it

rotund ravine
sterile token
ionic dagger
#

if i wanted to store it so i can give it a name called poopy fart or if i wanted to store it for readability or for whatever

rotund ravine
#

There is no need to store it if you are just killing anyone who touches a door

ionic dagger
#

people store data for shits and giggles

rotund ravine
#

?

ionic dagger
#

but how would i do that in this instance

rotund ravine
#

Where are you from?

ionic dagger
#

Blocktype bt = event.getClickedBlock().getType()?

rotund ravine
#

That’s a material, but yes

ionic dagger
#

or do i store it in material

#

so it would be in material

#

Material m = event.getClickedBlock().getType()

rotund ravine
#

Your programming jargon needs a refresher

#

But sure

ionic dagger
#

what do you mean

rotund ravine
#

I give up

ionic dagger
#

dawg i was wondering how to store it so i could know how to do so in the future

#

wasnt sure if it was a block or a material that i would have been storing

rotund ravine
#

This is not storing

#

@echo basalt Do you have a blockpost about declaring

ionic dagger
#

oh you were referring to my english

#

yes declaring a variable with that data

rotund ravine
#

Yes, i asked where you were from to tag someone from there to figure you out haha

ionic dagger
#

i am from america

rotund ravine
#

Oh

hazy parrot
#

Wow

rotund ravine
#

@wet breach This guy speaks ur language

echo basalt
#

like naming variables?

rotund ravine
echo basalt
#

just got home let me read up a bit

ionic dagger
#

i dont need help

#

i know the difference between the words, i was just not using the right ones

#

because it was too much effort tyyping that long word

echo basalt
#

yeah so

#

let's rephrase this a bit

#

Looking at your problem, let's structure this in a few simple steps

#

when a player clicks, check:

  • if the click is a right click
  • and the player clicked on a block
  • and the block that was clicked is a door

and if all those pass

  • kill the player
quaint mantle
#

@echo basalt so when we were talking about my abstract class storing data being incorrect

echo basalt
#

So the first thing a beginner would do is probably something like

@EventHandler
public void onClick(PlayerInteractEvent event) {
  if(event.getAction() == Action.RIGHT_CLICK_BLOCK) {
    if(event.getBlock().getType().name().contains("_DOOR")) {
      event.getPlayer().setHealth(0);
    }
  }
}
quaint mantle
#

did u want the individual characters to handle data themselves

echo basalt
#

Now, let's actually write some good code

quaint mantle
upper hazel
echo basalt
#

And we can do so by:

  • Assigning our variables so we don't call methods in checks
  • Applying guard clauses
quaint mantle
#

or maybe my repository class could store them

ionic dagger
#

checking the string is a nice idea

echo basalt
#

So it'll look like

@EventHandler
public void onClick(PlayerInteractEvent event) {
  Action action = event.getAction();
  Player player = event.getPlayer();
  
  if(action != Action.RIGHT_CLICK_BLOCK) {
    return;
  }

  Block block = event.getClickedBlock();

  if(!block.getType().name().contains("_DOOR")) { // underscore prevents trapdoor from triggering
    return;
  }

  player.setHealth(0);
}
ionic dagger
#

i made a substring of the last four characters and checked it that way

echo basalt
wet breach
upper hazel
#

bruh...

rotund ravine
#

Palettes are a thing now right?

upper hazel
#

is it possible without them?

echo basalt
#

uh yeah

ionic dagger
#

im kidding

#

i hate one line code

quaint mantle
ionic dagger
#

this is good thanks

echo basalt
echo basalt
#

Just try a bunch of stuff and see what works

storm crystal
#

should I make several commands in one class or every separate command in different classes?

echo basalt
#

ideally a class for each subcommand

#

if you have the time

echo basalt
#

it really depends

storm crystal
#

since those commands would be around the same topic

remote swallow
#

i think a lot of us do 1 per sub command

wet breach
storm crystal
#

I want to make commands for managing lootboxes

echo basalt
#

if your project is tiny then like

#

you might be fine with a couple command classes

storm crystal
#

1 for creating, 1 for removing, 1 for giving it

echo basalt
#

in my case I just have an entire engine that does stuff for me

echo basalt
#

and maybe a 4th class to link it all together

storm crystal
#

in what sense

upper hazel
wet breach
#

what do you mean can't change?

echo basalt
#

if you're using an engine / api you don't need a 4th class

storm crystal
#

I am not

#

I dont really know waht you are talking about either

echo basalt
#

but just something that implements CommandExecutor and does the logic for you

storm crystal
#

oh you mean

#

using main class with command executor?

echo basalt
#
public class MyBaseCommand implements CommandExecutor {

  private final Map<String, MySubCommand> subcommands = new HashMap<>();

  ...

#

does tab completion based on the subcommand list

rotund ravine
#

If u want to change behaviour of blocks fork soigot

echo basalt
#

it'd really be better if we just used a tree for this

upper hazel
upper hazel
#

no use events

storm crystal
#

yeah I dont really get much

echo basalt
#

think their idea was to just register a new block in the registry and mask it out when sending packets

#

so you can like easily check if the block is present innit

wet breach
#

especially if you are using resource packs as well

echo basalt
#

by behavior it's probably just extending the nms block class and adding/overriding logic

upper hazel
#

Well, for example, change the behavior of a block without using an event idk

echo basalt
#

data driven blocks

#

fork spigot if you want that

#

gl

upper hazel
#

or I didn't understand something

storm crystal
#

so from what im understanding making main class with command executor and just one class for each command is just fine?

echo basalt
#

the "proper" scalable way in the future is to make a sort of tree

#

where you have a "root" node that's your main commandexecutor class

#

and each child node can have its own child nodes etc

upper hazel
#

you are making some kind of plugin with 1000 commands?

echo basalt
#

uhh I guess

#

more like I am making a structure I can use across 100 plugins with 10 command each

sterile token
#

Ilussion would you command be free? Or u willl sell it source

storm crystal
echo basalt
#

Are you familiar with the concept of an object tree

echo basalt
#

not asking you

sterile token
#

A node is a group of things

echo basalt
#

no

sterile token
#

uhmn ok

#

But will you sell it? Or just private usage as what you have

rotund ravine
#

…

echo basalt
#

...

#

if you really really want a mediocre command system just look somewhere in my git projects

#

I don't sell my utilities

#

I sell products made with them :)

sterile token
#

oh right

#

What products you sell it uses it

echo basalt
#

commissions ..

ember estuary
#

Whats the best way of storing an ItemStack in MySQL?

echo basalt
#

Well

#

basically just serializing it

echo basalt
#

with nms you just get the nbt and serialize it

sterile token
#

Serializing the itemstack into a byte array

upper hazel
#

is there a plugin like deluxeMenu but with functional buttons?

echo basalt
#

with bukkit something something bukkitobjectoutputstream

#

not good

#

no better alternative

#

with paper there was a serialize method somewhere

#

p sure people were talking about itemmeta.toString giving nbt

rotund ravine
sterile token
#

also i ask, why dont they already implement that into bukkit

#

A good serializer and deserializer for items

#

Are those things i see spigot not satisfied really good

echo basalt
#

just do it yourself and pull request if you really want to see it

sterile token
#

yeah if we wait spigot team to look up it

#

Imagina if they takes months for support emails

echo basalt
#

you can just sign the cla and write it

#

there's no dedicated "spigot team" per se

#

well

#

There is the administration team

#

they handle the forums and discord server

#

There's also md and some other contributors

#

but it's not a company

sterile token
#

yeah if spigot where a company it would succed a lot. Not saying spigot work is not good

storm crystal
#

havent heard it yet

echo basalt
#

Y'know how recursion works right

sterile token
#

Also ilussion how about your hour? $$

storm crystal
#

yes

echo basalt
#

You know how a linkedlist works

storm crystal
#

not really

echo basalt
#

Alright let me write you a basic impl

#
public class Node<T> {

  private final T value;
  private Node<T> next;
  private Node<T> previous;

  public Node(T value) {
    this.value = value;
  }

  public Node<T> getNext() {
    return next;
  }

  public Node<T> getPrevious() {
    return previous;
  }

  public void setNext(Node<T> next) {
    this.next = next;
  }

  public void setPrevious(Node<T> previous) {
    this.previous = previous;
  }
}
#

This is a node

#
public class LinkedList<T> {

  private Node<T> head;
  private Node<T> tail;

  public void add(T value) {
    Node<T> node = new Node<>(value);
    
    if(head == null) {
      head = node;
      tail = node;
    } else {
      tail.setNext(node);
      tail = node;
    }
  }

  public T get(int index) {
    if(head == null) {
      return null;
    }

    Node<T> current = head;
    int pos = 0;

    while(pos++ < index || current == null) {
      current = current.getNext();
    }

    return current == null ? null : current.getValue();
  }
}
#

type deal

upper hazel
#

this passble create texture for placed blocks?

storm crystal
#

what does T stand for?

echo basalt
#

T is a generic type

#

It's basically context

#

So if I create a List<Boolean>, every T gets replaced with Boolean

#

you can set some constraints and use those constraints in methods

#

for example if you specify <T extends Number>

#

you can use every method present in Number in any T object

#

you can do some crazy witchcraft magic

storm crystal
#

oh so if I want to make List of strings it would be List<String> ye?

echo basalt
#

ye

storm crystal
#

okay

echo basalt
#

But yeah the idea of a Node in linkedlist is a sort of object wrapper that contains another Node as its parent / child

#

or in this case

#

parent is previous, child is next

#

With a tree, you have a list of children

quaint mantle
#

is there any way to force a scoreboard line to be centered?

echo basalt
#

well

#

no

upper hazel
echo basalt
#

you need to know the length of each character

storm crystal
#

hm, im still pretty confused about how to utilize it in practice

echo basalt
#

Alright so

#

With commands

#

You know how each subcommand can have multiple subcommands?

#

that's the idea

#

let's take a look at a luckperms command for example

storm crystal
#

so in my scenario it would be /lootbox add/remove/give?

#

as in 3 subcommands for /lootbox

echo basalt
#

Think of it like

quaint mantle
storm crystal
echo basalt
#

your tree would look like this

storm crystal
#

okay

echo basalt
#

The cool thing about having your nodes

#

is that you can add like

#

requirements for nodes

#

For example, players can only run XYZ commands

#

and the "give" command requires a permission

ionic dagger
#

hey another question

echo basalt
#

With those requirements, you can filter out nodes in tab completion and execution

storm crystal
#

so Id need a 4th class that would be a node?

echo basalt
#

Well your solution is fine

#

but if you want to build a full command system for future projects you'll want this in mind

ionic dagger
#

if i want to run something say every second, how would i do that? i tried Thread.sleep(1000), but threw an error

echo basalt
#

?scheduling

undone axleBOT
hazy parrot
#

You basically never want to sleep a thread

storm crystal
#

for now my next project would be to make a plugin that would work with custom damage, mobs, player stats and weapons

#

I got them done in separate plugins but I wanna merge them

echo basalt
#

BuT yeah the cool thing about this tree structure is that you can loop incrementally

#

For example, if I run the /lootbox give ImIllusion command

ionic dagger
#

difference between scheduler and runnable?

echo basalt
#

it grabs the "lootbox" node

ionic dagger
#

is there any significant difference in this case

echo basalt
#

matches give to all my nodes, finds the give node

#

and if I don't have that node's permission, it stops iterating there

storm crystal
#

if you do, it finds correct lootbox?

echo basalt
#

and if I have the permission, we repeat the process for the give node

#

grab next word, match it against all nodes

storm crystal
#

in that case it'd have to loop through config

echo basalt
#

or some cached thing

#

But yeah

storm crystal
#

like a hash map?

echo basalt
#

The other thing is that you don't want to match the node's name

#

but have a sort of argument system

#

In my command system every node has a name and an argument

#

The argument is responsible for validation and tab completion

#

The node name lets me get the value of an argument in execution

storm crystal
echo basalt
#

yeah

storm crystal
#

I mean the PDC tags

#

you search with a key but use it's assigned value later on

echo basalt
#

yeyeye but it's somewhat recursive

upper hazel
#

what is the best way to store big data in a hash?

storm crystal
# echo basalt

so here give remove add are children and parent is lootbox?

echo basalt
#

uhh no

#

well

#

lootbox is a node with no parent and the children are add, remove, give

#

add is a node with the parent lootbox and the children are <lootbox> or whatever you name it

storm crystal
#

oh okay

#

so things above are parents

echo basalt
#

<lootbox> is a node with the parent add and the children are <player> or whatever you name it

#

yeah

storm crystal
#

and things below are children

echo basalt
#

think of a family tree

storm crystal
#

is there a term of grandparent

echo basalt
#

well

storm crystal
#

or does it not go that far

echo basalt
#

you don't need to go that far

#

you can get as many parents as you want by just looping through parents

storm crystal
#

anyway I get the idea

#

ill do it my way first to tidy things up in my plugin

#

and then try to improve it with that new thing

echo basalt
#

yeah this is overkill

#

damn I just sneezed hard and now I'm light headed

storm crystal
#

oh yeah one more question about plugin size, since Id most likely do 3 commands ( give/spawn, add to config, remove to config) for custom weapons and mobs, and use their assigned stats along with player custom stats in damage formula to set health bars and such, would it be fine to do in one plugin?

#

assuming that I would keep it tidy, more or less

slender elbow
remote swallow
#

emily

#

have you heard

echo basalt
#

Dad? I'm a leaf node

#

oh yeah I get to keep my pink name this month

storm crystal
#

is it theoretically possible to make custom mobs by animating blocks with armor stands?

#

or is it too much for server to handle?

echo basalt
#

isn't that just modelengine

grim hound
#

Many people already do it

storm crystal
#

im not really sure how it can be handled

grim hound
#

You tick through it ever server tick

storm crystal
#

I mean I dont really know what kind of already existing tools can be used to make such things possible

#

if they do

grim hound
#

And calculate the next animation

#

And then just set the animation, that's it

grim hound
echo basalt
#

yeah it's just a packet now

storm crystal
#

I have a question about commands, first String s is the first parameter, as in if I wanted to do "/lootbox give", and the String[] strings would be next parameters that would be player, amount, type etc.?

sterile token
storm crystal
#

oh

#

so it basically depends on how many arguments I need?

#

if I want more than 1 then I use strings?

ember estuary
#

if you do "/lootbox give", the "give" will be in string[0]

hazy parrot
#

To join that array

storm crystal
#

huh

hazy parrot
#

Example String[] foo = {a, b, c}, String bar = String.join(foo, " ") would be equal to "a b c"

#

If you want to chain more that 1 argument

storm crystal
#

okay okay

#

but I can do something like this?

ember estuary
#

"/lootbox give DuskTaler 5 someType"
Will give you
s -> "lootbox"
strings -> ["give", "Dusktaler", "5", "someType"]

storm crystal
#

OH okay

#

so s is the very first thing

ember estuary
#

yep, s is the command itself

storm crystal
#

okay I gotta rename those

#

lmao

hazy parrot
ember estuary
#

i always call that variable "command" and the other variable (called "strings" in your example) "arguments"

hazy parrot
#

You want always to check number of arguments first

grim hound
ember estuary
#

(just so he knows why :D)

storm crystal
ember estuary
#

yes

storm crystal
#

well and also some kind of debug message to player like "you didnt provide enough parameters"

hazy parrot
#

Sure, it would be nice to send some error message to player too

storm crystal
#

okay I get it entirely now thank you

ember estuary
#

Wait, should one not return true on error?

storm crystal
#

when do I return true or false

hazy parrot
#

I think true is when command succeeded and false otherwise

#

But no one use that anyway xd

ember estuary
#

ah, lol, good to know

storm crystal
#

ig some debugging shenanigans

hazy parrot
#

Docs should have exact explanation

ember estuary
#

i have it the wrong way around in my plugins then haha

hazy parrot
#

I may be wrong

wet breach
#

if you return false, the server assumes the user didn't have permission and will display a no permission message, either the default is sent or a custom one if one was specified in plugin.yml

#

typically if you want a more customized error, you return true but send your custom error message

ember estuary
#

Executes the given command, returning its success.
If false is returned, then the "usage" plugin.yml entry for this command (if defined) will be sent to the player.

hazy parrot
#

Doesn't it return like command usage?

ember estuary
#

is what the docs says

#

yea true

wet breach
#

one of them two is returned XD

ember estuary
#

ah, so if usage is defined, it returns that, else it returns "no permission" ?

wet breach
#

if it says it returns the command usage if its false, then that it what it will return

#

which makes sense because if the command failed, then obviously something was wrong with the command

storm crystal
#

PDC works on entities right?

river oracle
#

yeah

storm crystal
#

neat

devout tartan
#

Where do we issue bot commands?

#

(since there is no bot chat, i'm guessing anywhere?)

#

?help

undone axleBOT
#
CafeBabe Help Menu
*Red V3*
__**Admin:**__

selfrole Add or remove a selfrole from yourself.

__**Cleanup:**__

cleanup Base command for deleting messages.

__**Core:**__

embedset Commands for toggling embeds on or off.
info Shows info about CafeBabe.
licenseinfo Get info about Red's licenses.
mydata Commands which interact with the data CafeBabe has about...
set Commands for changing CafeBabe's settings.
uptime Shows CafeBabe's uptime.

__**Downloader:**__

findcog Find which cog a command comes from.

__**Mod:**__

names Show previous usernames, global display names, and server...
userinfo Show information about a member.

__**ModLog:**__

listcases List cases for the specified member.
reason Specify a reason for a modlog case.

__**Permissions:**__

permissions Command permission management tools.

olive vault
#

can I pay someone to convert a script to a java plugin?

#

its a complex and advanced script

olive vault
#

dms

devout tartan
#

... found the bot chat

smoky oak
#

how do generics work again?

hazy parrot
smoky oak
#

its only relevant in this method

#

do i still need to do it on class level?

dry hazel
#

you can do it at the method as well

hazy parrot
#

public <T> List<T>

#

But I don't get why do you need generic here

dry hazel
#

maybe not void lol

hazy parrot
#

Yeah not void

#

But u get the idea

smoky oak
#

so i know how they work

#

i keep forgetting

olive vault
#

anyone else?

olive vault
hazy parrot
#

?services

undone axleBOT
acoustic stag
#

how to set color of banner itemstack? i have DyeColor and want to set color of crafted banners to that dyecolor

pseudo hazel
#

I am 80% sure each color banner is it's own item

acoustic stag
#

yeah i know that, but if i have dyecolor then how can i change the item based on that dyecolor?

pseudo hazel
#

probably with a switch

storm crystal
#

is there EntityType equivalent of Material type = Material.matchMaterial(typeName);?

pseudo hazel
#

fromName()

storm crystal
#

what does this mean?

echo basalt
#

deprecation means it's still functional but there's a better alternative

#

and should be avoided / due for removal

pseudo hazel
#

usually*

echo basalt
#

For example, StringBuffer is deprecated in favor of StringBuilder

storm crystal
#

well I want to get entity type from config

storm crystal
#

so I did this

storm crystal
worldly ingot
#

Yes, Registry.MATERIAL

storm crystal
#

okay thats pog

echo basalt
#

You seem to have a custom config class already

#

how about you extend it and read all the values there instead of doing it on your method

pseudo hazel
#

cool I didnt know registry was a thing

worldly ingot
#

It's a relatively new method though so be weary of that. 1.19 or so

pseudo hazel
#

is that why they deprecated fromName?

echo basalt
#

I need to write a huge post regarding good code

worldly ingot
#

No, fromName() has been deprecated for some time now

#

It's not reliable

echo basalt
#

might put it both in my gist and here

echo basalt
#

actually yeah I might just make a git repo with a backup of every single index post

pseudo hazel
#

so what would be the alternative if you dont have access to the registry class

storm crystal
#

do I just make a method that reads config into list?

worldly ingot
#

Probably just the regular Enum#valueOf() methods, but Registry is 1.13+ so you should have access to it in most scenarios

#

If you don't have the match() method however, which is newer, you have NamespacedKey#fromString(String) which you can then pass into Registry#get()

#

And if you don't have NamespacedKey#fromString() you can copy its implementation from Bukkit 😛

pseudo hazel
#

okay thats what I meant

#

I see

echo basalt
#

done

#

gotta write one about good code practices

storm crystal
#

uh

#

I changed my main class name

#

from Customdamage to CustomDamage

#

now it says that it cant find the class

#

I changed it in Maven file and reloaded it as well

pastel axle
#

did you update plugin.yml

storm crystal
#

oh

#

I forgor about this part

tribal cypress
#

Why is my IntelliJ trippin?

#

within this method

lost matrix
#

You did probably cast it to Player before checking

tribal cypress
#

didn't cast it anywhere

#

I'll paste the whole code, gimme a sec

lost matrix
#

Show your whole code then

tribal cypress
alpine swan
#

I’m not really familiar with persistentdatacontainers, can you just use them for permanent data storage on a player (assuming their data file isn’t deleted) instead of using a database or something

lost matrix
alpine swan
tribal cypress
#

As far as I know, it will persist as long as the world file is intact

#

As that's the place where the data is stored

lost matrix
tribal cypress
#

Oh, true

#

Nvm, solved, I just didn't have Player imported

#

Thanks for pointing out

#

Also is the selectedList variable alright? I was thinking doing it this way, but dunno if the variable just points to the list or if it copies the list. Either way is okay I guess, but if it copies the whole list I'm just taking more memory for no reason..

umbral ridge
lost matrix
storm crystal
#

I dont get it, why it doesnt print any parameter when I provide it?

lost matrix
storm crystal
#

okay it does, my bad, but I get "input must not be null" exception

umbral ridge
#

How are teleportation requests usually handled?

Could I do this? Is that efficient?

private HashMap<Player, HashMap<Player, Integer>> teleporters = new HashMap<>();

Player is a player who recieved a request

HashMap<Player, Integer> is a player that sent the request to the player, also the Integer for scheduler runTaskTimer that counts down the teleportation request seconds (eg. expires in 120 seconds)?

good idea? any way to do this differently?

chrome beacon
#

You don't need to store a ticking int

#

Just store an end time

#

also keeping a reference to the player object isn't ideal

#

try to avoid that

echo basalt
#

I'm thinking of uhh

drowsy helm
#

Use a pair or tuple

umbral ridge
drowsy helm
#

Or class

#

No use a hashmap initially

#

Just dont nest the hashmap

umbral ridge
#

ohh

drowsy helm
#

Hashmap<uuid, pair<uuid, integer>> or
Hashmap<uuid, teleport request class or record>

umbral ridge
#

yeah

#

looking good

#

thank you

#

I might make a class for it

#

Would be cleaner..

drowsy helm
#

Yeah no point having a collection for something that is always 1 element

echo basalt
#
public class TeleportRequest {

  private final UUID requestId = UUID.randomUUID();

  private final UUID senderId;
  private final UUID targetId;

  private int ticksLeft;

  public TeleportRequest(UUID senderId, UUID targetId, int ticksLeft) {
    this.senderId = senderId;
    this.targetId = targetId;

    this.ticksLeft = ticksLeft;
  }

  getters and setters innit
}
private static final int TELEPORT_TICKS = 15 * 20; // 15 seconds

private final Map<UUID, TeleportRequest> requests = new ConcurrentHashMap<>();

public TeleportRequest createRequest(UUID senderId, UUID targetId) {
  TeleportRequest request = new TeleportRequest(senderId, targetId, TELEPORT_TICKS);
  this.requests.put(request.getRequestId(), request);
  return request;
}
#

or whatever

#

this is just a solution

#

there are like 20 others

umbral ridge
#

I havent heard about ConcurrentHashMap before

#

xD

drowsy helm
#

*sends whole solution

#

Or whatever

storm crystal
#

I think im a bit confused on how to manage PDCs on entities

#

im getting this

pseudo hazel
#

whast on line 43

storm crystal
pseudo hazel
#

okay

#

so then typename is null

#

what does getCustomConfig return

storm crystal
#

I checked and it returns null

#

thats weird

#

cuz it does have spider

pseudo hazel
#

I mean you should check if the enemy name is valid

#

since this will also crash when you just typo

#

and I would put the getString part in the actual enemiesconfig class

#

so you dont have to worry about deserializing the data every time, but only in the place where you actually store it

storm crystal
#

maybe

pseudo hazel
#

then you can just do enemiesConfig.getEnemy(enemyName)

#

or something

storm crystal
#

let me actually solve the problem first

#

not optimize code

pseudo hazel
#

and the enemy has a type, health, etc

#

okay

#

print the config

#

how do you know its reading the file correctly

storm crystal
#

why wouldnt it

umbral ridge
echo basalt
#

uh no

#

the uuid in the map is the request id not a player's id

umbral ridge
#

I see now yeah

#

i overlooked this lol

lost matrix
#

*You need this request id if you want to get the request back from a clickable component for example

umbral ridge
#

Yeah

#

great

storm crystal
#

I see why

#

I put wrong config in dependency injection

echo basalt
#
public Collection<TeleportRequest> getIncomingRequests(UUID playerId) {
  return getRequests(request -> request.getTargetId().equals(playerId));
}

public Collection<TeleportRequest> getOutgoingRequests(UUID playerId) {
  return getRequests(request -> request.getSenderId().equals(playerId));
}

public Collection<TeleportRequest> getRequests(Predicate<TeleportRequest> predicate) {
  Set<TeleportRequest> requests = new HashSet<>();

  for(TeleportRequest value : this.requests.values()) {
    if(predicate.test(value)) {
      requests.add(value);
    }
  }

  return requests;
}

public TeleportRequest getRequest(UUID requestId) {
  return this.requests.get(requestId);
}
#

something like this

umbral ridge
#

You didn't have to do this I really appreciate it xD

storm crystal
#

how can I set enemy health above their natural health?

echo basalt
#

you set the new max health

#

by adding an attribute modifier

storm crystal
#

how should modifier look like?

echo basalt
#

new AttributeModifier

#

pick one

storm crystal
#

I dont get it

echo basalt
#

AttributeModifier myModifier = new AttributeModifier("extra-health", 25, Operation.ADD_SCALAR) or whatever

smoky oak
#

qq why does both

player.damage(value, player2)
player.setLastDamage(magicEvent)

and

player.setLastDamage(magicEvent)
player.damage(value, player2)

return for DeathEvent::getEntity().getLastDamageCause().getCause() ENTITY_ATTACK? Shouldn't at least one of them return MAGIC?

#

or does that only work if i remove player2?

storm crystal
#

or do I need to know mob's base hp?

smoky oak
storm crystal
#

but with this method

echo basalt
#

you can just get the current value

#

subtract

#

add

storm crystal
#

okay

#

how do I set it

echo basalt
#

you get the attribute

#

and you add the modifier

left pine
#

Hello, I wanted to know how I could obtain multiple paths this way:

echo basalt
#

well

#

you can get the slots section, loop through its keys and get the section

storm crystal
#

like that?

echo basalt
#

try it

storm crystal
#

well didnt work

#

spider is at 16/2048

echo basalt
#

yeah

#

now you set the new health

#

after adding the modifier

smoky oak
#

hm setting the last damage cause to EntityDamageByEntityEvent with MAGIC and calling player.damage(double) returns a EntityDamageEvent for some reason

#

is there a simple way to check 'yes, this code caused that death' or is my only option to throw a double in it that'll never occur naturally?

storm crystal
#

how can I round a float to like 1 number after , ?

smoky oak
#

% 1

#

oh wait

#

i read your question wrong

#

Math.round(number * 10) / 10

storm crystal
#

thanks

worldly ingot
#

If you're doing this for user output (i.e. a chat message), consider a DecimalFormat

storm crystal
#

yeah it didnt work well

#

it gave me 2 numbers after comma

#

but after a few hits

#

it became this

rare ether
#
     double hp = 2.34568;
     DecimalFormat f = new DecimalFormat("##.0");
     string hpRounded  = f.format(hp);
#

this should work

smoky oak
#

yea doubles are dumb

#

btw choco do u have xp with custom damage?

#

im having issues with the events

worldly ingot
#

Keep the decimal format as a constant though please

#

Doesn't need to be rebuilt every time

smoky oak
#

ill take your lack of response to my question as a no then lol

worldly ingot
#

Not sure what you mean with custom damage

smoky oak
#

like

#

i need to check in player death if they died to custom damage

worldly ingot
#

You could use item attributes or just the damage event to change the damage calculation

#

oh

smoky oak
#

but it just tells me 'Have an EntityDamageEvent'

worldly ingot
#

Could assign some metadata to the player if you'd like and check it in the event

left pine
#

Could someone tell me how I can create a for to go through a list with this?

slots = config.getConfigurationSection("slots"); slot = slots.getInt("slot"); item = slots.getString("itemType");

smoky oak
#

yea but how would i know that that metadata is still correct?

worldly ingot
#

Assign a timestamp to it

smoky oak
#

no liek

#

oh wait

#

hm

worldly ingot
#

If the timestamp exceeds 5 seconds or something, discard

smoky oak
#

no no its only relevant in the same tick anyway

#

cuz yknow either u die or u dont

#

good idea

#

a player can only take damage from one source per tick if you set them invlun, correct?

worldly ingot
#

Unsure what the default invuln ticks are

smoky oak
#

like

#

it just needs to be mroe than 0

#

if i call player.damage twice, would it damage them twice? in the same tick i mean, thats what im worried about

worldly ingot
rare ether
#

Cancelling piston head movement

storm crystal
#

number.000004 for example

#

okay I just forgot to format it in enemy name

#

now it works perfectly

#

I think ill have to rewrite this plugin though

#

since I made it specifically for already existing mobs

#

and now I just remade it for custom ones

#

so its kinda messy

smoky oak
#

yall i got the weirdest dupe glitch ever

#

so i want to drop iteps past a threshold when an inventory is closed

#

works fine but if items are in the inventory it dupes the items in the inventory

#

im assuming my code runs first, drops the items, then the event finishes, doesnt use the changed inventory, and resets it to full + whatever was in the anvil slot

#

anyone an idea how to bypass this?

#

like if possible without a 1 tick delay

#

@ivory sleet iirc u helped me with this before but it could've been any other of the orange/pink people

ivory sleet
#

can u dumb it down

smoky oak
#

so i want to limit items in inventory to set caps on stuff like golden apples

#

for some reason when i remove items from the player inventory to drop them when closing an anvil, it dupes the item, and it looks like the event just ignores the changes i made to the inventory and overwrites the player inventory

#

it only happens if there are items in the anvil slots, so it must be something with what the event does when adding the items back to the player inventory

#

@ivory sleet

#

hm ill check if removing the items from the anvil during the event might do it, if it doesnt, ill come back

storm crystal
#

how to use that bottom bar above your inventory to show messages to player?

#

like here on Hypixel

worldly ingot
#

Is that not just the item's name?

rare ether
storm crystal
#

yes

rare ether
#

Player.sendActionBar()

worldly ingot
#

The action bar is the top message (mining & the percentages). The one below is just the item name afaik

#

At least that's what it looks like to me

storm crystal
#

yes thats true

#

I cropped it poorly

#

but I see now

#

thanks

rare ether
#

Resolved, tysm ❤️

storm crystal
#

Is it possible to remove description from items like potions?

river oracle
#

if that doesn't work try using ItemFlag#HIDE_ATTRIBUTES

#

as that hides other stuff such as damage etc

echo basalt
#

anyone got any idea how I can do like a styled code block inside a markdown html section

#

it's just shitting the bed

echo basalt
#

no

umbral ridge
#

or html in general?

echo basalt
#

markdown

umbral ridge
#

oh idk about markdown. Where is it

echo basalt
umbral ridge
#

yeah

#

1sec

echo basalt
#

that's basically it

#

writing a new one

#

this is a big one

#

might post here over multiple messages

umbral ridge
#

O nice

echo basalt
#

nah it's fine I just ditched the spoiler blocks

#

imma post it in discord too

#

will probably do it over multiple messages

umbral ridge
#

Its 5am i probably wont be here when you post it. Ill wake up at 2..3 pm again lol

echo basalt
#

4am here

#

yikes I'm at 4k characters

umbral ridge
#

But ive finished the teleportation functionality

umbral ridge
#

im working on mine locally, then ill just upload it to the server

echo basalt
#

just making a markdown copy of my search index

umbral ridge
#

one day

thin iris
#

‘’’java
code
‘’’

echo basalt
#

breaks in another way

thin iris
#

huh..?

#

it shouldnt lmfao

#

make a new repo go to readme and put that in and itll format for you

echo basalt
#

still brokey

#

trust me I tried

#

I just gave up on it

#

and the new solution is discord friendly

thin iris
#

i’m literally looking at code using that rn

echo basalt
#

that code works

#

mine doesnt

#

I have no idea why

#

just trust me it's fine

#

ILLUSION SEARCH INDEX - Good Habits (Click me)

Don't nest, use guard clauses

When writing multiple checks, rather than nesting, aim to apply guard clauses in order to keep your code as flat as possible.

Non-compliant code:

public void doSomething() {
  if(myConditionOne()) {
    doSomethingFirst();
    if(myConditionTwo()) {
      doSomethingSecond();
    }
  }
}

Compliant code:

public void doSomething() {
  if(!myConditionOne()) {
    return;
  }

  doSomethingFirst();

  if(!myConditionTwo()) {
    return;
  }

  doSomethingSecond();
}

When naming variables, use descriptive, intuitive names:

A common mistake is to use short names for variables, such as "p" for player, or "i" for index. This is bad practice, as it makes your code harder to read and understand. Instead, use descriptive names, such as "player" or "index".

It's fine to use a single-letter variable name depending on context. It is common to see i used in for loops, x, y, z when dealing with math and catch(Exception e) blocks.

Non-compliant code:

@EventHandler
public void onPlayerJoin(PlayerJoinEvent e) {
    Player p = e.getPlayer();
    p.sendMessage("Welcome to the server!");
}

Compliant code:

@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
    Player player = event.getPlayer();
    player.sendMessage("Welcome to the server!");
}

Re-use variables when possible:

Many common methods will return a new object in every call, a few common ones are:

  • Player#getLocation
  • Location#getBlock
  • ItemStack#getItemMeta
  • Enum#values

Following this practice will also result in cleaner code, with the added bonus of being more performant.
Non-compliant code:

@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
    boolean standingOnGround = event.getPlayer().getLocation().getBlock().getType() == Material.GRASS_BLOCK ||
            event.getPlayer().getLocation().getBlock().getType() == Material.DIRT;
    
    if(standingOnGround) {
        event.getPlayer().sendMessage("You're standing on grass or dirt!");
    } else {
        event.getPlayer().sendMessage("You're not standing on grass or dirt!");
    }
}

Compliant code:

@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
    Player player = event.getPlayer();
    Location location = player.getLocation();
    Block block = location.getBlock();
    
    Material blockType = block.getType();
    
    boolean standingOnGround = blockType == Material.GRASS_BLOCK || blockType == Material.DIRT;
    
    if(standingOnGround) {
        player.sendMessage("You're standing on grass or dirt!");
    } else {
        player.sendMessage("You're not standing on grass or dirt!");
    }
}

Avoid repeating collections calls:

Map#containsKey and Map#get can be merged as Map#get and checking for null.
Map#keySet and Map#get can be merged as Map#entrySet and iterating over the entries.
Map#containsKey and Map#remove can be merged as Map#remove.
Map#containsKey and Map#put can be merged as Map#putIfAbsent.

Non-compliant code:

public void doSomething(Map<String, Integer> map) {
    if(map.containsKey("key")) {
        Integer value = map.get("key");
        map.remove("key");
        map.put("key", value + 1);
    }
}

Compliant code:

public void doSomething(Map<String, Integer> map) {
    map.computeIfPresent("key", (key, value) -> value + 1);
}

Perform the most performant checks first

When checking for multiple conditions, always check the most performant ones first.

Non-compliant code:

public boolean isApplicable(Player player) {
    return checkBlocks(player) && checkInventory(player) && player.isOp();
}

Compliant code:

public boolean isApplicable(Player player) {
    return player.isOp() && checkInventory(player) && checkBlocks(player);
}

(More below)

#

_ _

Don't expose mutable collections

When returning a collection, make sure to return an immutable copy of it, to prevent the caller from modifying it.

Non-compliant code:

public class MyManager {
   
   private final Map<UUID, PlayerData> playerData = new HashMap<>();

   public void setPlayerData(UUID uuid, PlayerData data) {
        playerData.put(uuid, data);
   }
   
   public Map<UUID, PlayerData> getPlayerData() {
        return playerData;
   }
}

Compliant code:

public class MyManager {
   
   private final Map<UUID, PlayerData> playerData = new HashMap<>();

   public void setPlayerData(UUID uuid, PlayerData data) {
        playerData.put(uuid, data);
   }
   
   public Map<UUID, PlayerData> getPlayerData() {
        return Map.copyOf(playerData);
   }
}

Follow SOLID and DRY principles

SOLID is an acronym that encompasses five simple principles:

Single Responsibility Principle

A class should have one, and only one, reason to change. A class should only have 1 role.

Non-compliant code:

public class MyListener implements Listener {
    
    private final Map<UUID, PlayerData> playerData = new HashMap<>();
    
    @EventHandler
    private void onJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        UUID playerId = player.getUniqueId();
        
        PlayerData data = new PlayerData(playerId);
        this.playerData.put(playerId, data);
    }
    
    @EventHandler
    private void onQuit(PlayerQuitEvent event) {
        Player player = event.getPlayer();
        UUID playerId = player.getUniqueId();
        
        this.playerData.remove(playerId);
    }
}

This example violates the Single Responsibility Principle because our class is performing two roles: Data Management, and Event Listening.
Following SOLID principles, we need to split this class into 2 classes, one for each role.

Compliant code:

public class MyDataManager {

    private final Map<UUID, PlayerData> playerData = new HashMap<>();
    
    public PlayerData getPlayerData(UUID playerId) {
        // Feel free to check argument validity here
        return this.playerData.get(playerId);
    }
    
    void handleJoin(Player player) {
        UUID playerId = player.getUniqueId();
        PlayerData data = new PlayerData(playerId);
        this.playerData.put(playerId, data);
    }
    
    void handleQuit(Player player) {
        UUID playerId = player.getUniqueId();
        this.playerData.remove(playerId);
    }
}
public class MyListener implements Listener {
    
    private final MyDataManager manager;
    
    public MyListener(MyDataManager manager) {
        this.manager = manager;
    }
    
    @EventHandler
    private void onJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        this.manager.handleJoin(player);
    }
    
    @EventHandler
    private void onQuit(PlayerQuitEvent event) {
        Player player = event.getPlayer();
        this.manager.handleQuit(player);
    }
}

Open-Closed Principle

You should be able to extend a classes behavior, without causing breaking changes.

Non-compliant code:

public class PetCreator {

    public Pet createPet(String type) {
        return switch(type) {
            case "chicken" -> new PetChicken();
            case "cow" -> new PetCow();
        });
    }
}
#

This example violates the Open-Closed Principle because it's not open for extension. If another project or module wants to register their own pet, they'd need to change the code.
To make this code compliant, we need to switch to a more functional approach.

Compliant code:

public class PetCreator {

    private final Map<String, Supplier<Pet>> providers = new HashMap<>();
    
    public void registerPet(String type, Supplier<Pet> supplier) {
        // Feel free to check argument validity here.
        this.providers.put(type, supplier);
    }
    
    public Pet createPet(String type) {
        Supplier<Pet> supplier = this.providers.get(type);
        
        if(supplier == null) {
            return null;
        }
        
        return supplier.get();
    }
}

Liskov Substitution Principle

Classes should be replaceable by their subclasses, without breaking the code.

Non-compliant code:

public interface Pet {

    void spawnAt(Location location);
    boolean isHungry();
    void despawn();
    
}
public class BoulderPet implements Pet { // Literally just a rock

    @Override
    public void spawnAt(Location location) {
        // Do something nice
    }
    
    @Override
    public boolean isHungry() {
        throw new IllegalStateException("Why would I be hungry? I'm a rock!");
    }
    
    @Override
    public void despawn() {
        // Do something nice
    }
}

This code violates the Liskov Substitution Principle because it breaks code flow under normal usage, and must be refactored.
Reworking code to follow the Liskov Substitution Principle requires refactoring it with other principles in mind. I'll refactor it in the principle below:

Interface Segregation Principle

Make fine grained interfaces that are client specific. It is better to have multiple small interfaces opposed to one big one.

Here's a suggestion on how the code from the previous principle can be refactored:

public interface Pet {

    void spawnAt(Location location);
    void despawn();
    
}
public interface FeedablePet extends Pet {

    boolean isHungry();
    void feed();
    
} 
public class CatPet implements FeedablePet {

    ...
    
}
public class BoulderPet implements Pet {

    ...
    
}

Dependency Inversion Principle

Depend on abstractions, not on concretions. You shouldn't depend on a specific implementation, but rather on an interface. This hides implementation details by providing a robust API, and allows you to define a boundary between API and implementation.

Let's rework one of the examples above.
Non-compliant code:

public class MyDataManager {

    private final Map<UUID, PlayerData> playerData = new HashMap<>();
    
    public PlayerData getPlayerData(UUID playerId) {
        // Feel free to check argument validity here
        return this.playerData.get(playerId);
    }
    
    void handleJoin(Player player) {
        UUID playerId = player.getUniqueId();
        PlayerData data = new PlayerData(playerId);
        this.playerData.put(playerId, data);
    }
    
    void handleQuit(Player player) {
        UUID playerId = player.getUniqueId();
        this.playerData.remove(playerId);
    }
}

Compliant code:

public interface MyDataManager {

    PlayerData getPlayerData(UUID playerId);
    
}
echo basalt
#
public class MyDataManagerImpl implements MyDataManager {

    private final Map<UUID, PlayerData> playerData = new HashMap<>();
    
    @Override
    public PlayerData getPlayerData(UUID playerId) {
        // Feel free to check argument validity here
        return this.playerData.get(playerId);
    }
    
    // This is hidden from the interface and only accessible through explicit typing
    public void handleJoin(Player player) { 
        UUID playerId = player.getUniqueId();
        PlayerData data = new PlayerData(playerId);
        this.playerData.put(playerId, data);
    }
    
    void handleQuit(Player player) {
        UUID playerId = player.getUniqueId();
        this.playerData.remove(playerId);
    }
}
public class MyListener implements Listener {
    
    private final MyDataManagerImpl manager;
    
    public MyListener(MyDataManagerImpl manager) {
        this.manager = manager;
    }
    
    @EventHandler
    private void onJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        this.manager.handleJoin(player); // Implementation detail
    } 
    
    @EventHandler
    private void onQuit(PlayerQuitEvent event) {
        Player player = event.getPlayer();
        this.manager.handleQuit(player);
    }
}

With the example above, we've refactored the MyDataManager class to hide the handleJoin / handleQuit methods by applying Dependency Inversion. This allows us to expose all the getter logic without exposing sensitive join/quit logic where it's not needed.

Use primitives when possible

Autoboxing and unboxing is a process where the compiler automatically converts between primitive types and their wrapper classes (int <-> Integer). This process is very expensive, and should be avoided when possible.
Use primitives when possible, and prefer using unboxed classes when possible. (Int2ObjectHashMap, IntSupplier, Predicate)

Non-compliant code:

Map<Integer, String> map = new HashMap<>();
map.put(1, "Hello");
map.put(2, "World");

String hello = map.get(1);

Compliant code:

Int2ObjectMap<String> map = new Int2ObjectOpenHashMap<>();
map.put(1, "Hello");
map.put(2, "World");

String hello = map.get(1);

Override uneccessary methods

When extending a class, make sure to override all methods that are wasteful, such as fire checks for custom ArmorStand entities.

Only optimize what needs to be optimized

Pre-mature optimization can severely affect code readability and maintainability. As a general rule of thumb, when experiencing performance issues, benchmark and optimize what is actually slowing you down.

PSA: Always seek to improve your code

This guide is not a set of rules, but rather a set of guidelines. It is important to understand that there is no such thing as perfect code, and that there is always room for improvement. Always seek to improve your code, and don't be afraid to ask for feedback. A second pair of eyes can help you spot mistakes you might have missed.

carmine mica
#

they are both useful tho.

#

unmodifiableMap will refelct changes in the underlying map

#

the copy wont

#

Int2ObjectHashMap is not a fastutil type

#

Int2ObjectOpenHashMap is probably what you want

echo basalt
#

yet another fix

placid moss
#

THe example for the most performance checks first doesn't really make any sense because in the and statement all of the conditions will need to be checked anyways right?

echo basalt
#

&& and & have a subtle difference when comparing booleans

#

Where if the first condition fails, the second condition doesn't run at all

#

Same with ||, if the first condition passes the second doesn't run

#

So in the case of player.isOp() && checkInventory(player) && checkBlocks(player);, the checkInventory method won't ever be called if player.isOp fails

#

Using the bitwise AND/OR (& / |) instead of the logical AND/OR (&& / ||) will result in both methods running regardless of outcome

cold pawn
#

Anyone know how to use the new PlayerInfoUpdatePacket for 1.20 (Protocol Lib)? Looking at the wiki, it's not to clear what i'm suppose to set, so any help would be amazing.

chilly hearth
upper hazel
#

who know what the "getLocalizedName " in itemMeta? how is it different from displayName

echo basalt
#

It's either a key or translated

upper hazel
#

wdym

#

what the key

carmine mica
#

that isn't used for anything. its just an arbitrary string that can be set

quaint mantle
#

hi

#

i have an error

#

and i don't know how to fix it

echo basalt
#

well

#

read the stacktrace

#

error points to line 32

#

the ide did warn you this could be null so you did the most braindead thing and wrapped with Objects.requireNonNull

#

9/10 chance the command isn't defined on your plugin.yml

quaint mantle
#

Ok, so I need to delete not null from all commands?

#

Becouse all plugin is registered in the plugin.yml

eternal oxide
#

"sprawdz" is not in your plugin.yml

quaint mantle
#

Ok

#

Thanks

rotund ravine
#

Tell him how @grim hound

#

Most of it can be translated to protocollib quite easily

grim hound
#

I don't really know what he wants to do

#

But for removing players I think there's a seperate packet now

#

Otherwise you just use the InfoAction enum

hushed spindle
#

is there some way to distinguish growing crops like carrots and potatoes that have a well defined max growth stage to crops like cactus or vines or sugar cane

#

or do i have to maintain a list of such exceptions

rotund ravine
tall dragon
#

yea but not for all :d

hushed spindle
#

thats the thing, sugar canes and vines and cactus are also all ageable

#

heck, even frosted ice is ageable

tall dragon
#

maybe u can use that

#

it might just return 1 for those idk

hushed spindle
#

i think it does just return 3 because thats when they stop growing

#

but ill double check

#

ah ok so the max age of sugar cane and cactus is 15, strangely enough

#

that of frosted ice is 3 though

#

bamboo max age is 1 though

#

and that of chorus flower is 5

#

doesnt seem very consistent to me

#

that of weeping and twisting vines is both 25 but during growth stages this goes all over the place

tall dragon
#

i guess you'll need to keep your own list ;d

hushed spindle
#

:(

tall dragon
#

which crops ru tryna target

hushed spindle
#

just trying to make a generic farming skill, so just the stuff you can farm

#

but like look

#

whats the consistency in this lol

icy beacon
#

Wtf

#

What does age even resemble then

hushed spindle
#

i have no idea lmao

icy beacon
#

Why do you need it then xD

hushed spindle
#

the only consistency i can see is that it goes up and down based on even/uneven y coordinate

#

but thats about it

#

and i dont need it its just a weird ass thing i found while testing lol

upper hazel
#

?paste

undone axleBOT
tall dragon
#

yea you'll just need to keep your own list of crops ur tryna target im afraid

#

i mean, its not that bad is it?

hushed spindle
#

not that bad but it just means i have to keep a closer eye on what changes between updates

#

and i hate having to pay attention

upper hazel
#

how can you check that object instanceof T?

hushed spindle
#

you cant do that with generics no

#

gotta do some ugly workarounds for that

upper hazel
#

do these workarounds affect optimization?

hushed spindle
#

as far as im aware no

hushed spindle
#

how do i check whats in the tag

#

ah nevermind ill just output it

#

yeah it doesnt have everything, like i'd also like to have berries and cocoa be in it

#

ill just go a manual list

tribal cypress
#

Hey, any idea what this error is trying to tell me?

rotund ravine
#

What are you trying to do

tribal cypress
#

Sort the list of games by players

rotund ravine
#

Like the amount?

tribal cypress
#

Yeah, the amount of players added

#

I know it can be done with list.sort, but I wanted to expand on my knowledge with the Stream API

rotund ravine
#

It doesn’t know how to compare

#

Or what to compare

tribal cypress
#

Oh, I may know the cause

#

Any way I can tell it to compare the size of the list?

eternal night
#

.sorted(Comparator.comparingInt(g -> g.players().size()))

tribal cypress
#

Thank you

eternal night
#

notably that has the lowest number at the front

#

if you only need the minimum/maximum there are special methods for that

tribal cypress
#

Also, why does there need to be comparingInt instead of comparing?

eternal night
#

you don#t

#

but comparing expects a Comparable

#

which means you'll be autoboxing the int returned by size for no reason

#

when comparingInt exists

tribal cypress
#

Ah, alright. Thanks!

glad prawn
tribal cypress
eternal night
#

Comparator.<Game>comparingInt(g -> g.players().size()).reversed()

#

notably this cannot infer the generic type of g because you chain it into a .reversed call

#

so you have to manually define it

chilly hearth
glad prawn
#

Husk extends Zombie, so Husk is Zombie

chilly hearth
#

oh

#

but

#

if i set husk tag to zombie one

#

it will create a problem as i have other functions depending on the tag

glad prawn
chilly hearth
#

oh

#

let me trey

wooden hearth
#

Hey, can anyone link me to any good tutorials on using Mysql with spigot thank you

tall dragon
#

mysql does not have anything to do with spigot

shadow night
#

I'm pretty sure there are tutorials for that tho

cold pawn
icy beacon
#

How do I reset my stash password?

rotund ravine
#

?support

undone axleBOT
rotund ravine
#

Ask md

icy beacon
#

Ty

slate tinsel
#

Hello! I'm trying to make it possible to launch a player in the air right now I'm using "setVelocity" and "new Vector(0, speed, 0);". And then make it so that when the player has ridden a certain number of blocks, the player will not ride up anymore but the player will continue to ride up. Is there any other way to do this because putting "new Vector(0, 0, 0)" looks very bad.

chrome beacon
#

You're better off calculating a vector that will launch the desired height