#help-development

1 messages · Page 1947 of 1

lost matrix
#

Just make a double check using .isBlock() ...

sweet lance
willow stream
#

hey smile, I've tried using Player#getVelocity instead of updating a HashMap on PlayerMoveEvent and the values were too different to be considered usable, I just made the calculation in the event async and am updating the map with it just when needed

#

I reckon that this is a better and more lightweight solution since I can't use the new method

chrome beacon
#

?xy

undone axleBOT
chrome beacon
#

What is the goal here

willow stream
#

I've already explained it before, I'm too lazy to repeat myself haha let me find the messages

lost matrix
willow stream
#

explanation starts from here

long dew
#

any plugs that completly remove beds from the server?

willow stream
#
new: -0.04258525346874389 0.0030162615090425808 -0.14383933002623553```
chrome beacon
#

Could you show your code? Also as smile said this shouldn't be done async

willow stream
#

I've never done anything async so please tell me if this is useless and/or bad:

@EventHandler
public void onMove(PlayerMoveEvent event) {
  Location start = event.getFrom(), end = event.getTo();
  Bukkit.getScheduler().runTaskAsynchronously(this.manager.getPlugin(), () -> {
    start.subtract(end);
    start.setY(start.getY() / 2.0);
    this.finalSpeed = start.length();
  });
}
#

the calculation takes place async, map gets updated in the EntityDamageByEntityEvent

dusky sky
#

can anyone provide a worledt plugin for 1.8.9 which can load a heavy schematic

buoyant viper
lost matrix
dusky sky
willow stream
#

the only reason why I made it async is because it's used a lot

lost matrix
lost matrix
dusky sky
willow stream
#

should I remove the scheduler then and just update the map there or return a double and update the map using the double only when needed?

willow stream
grand venture
#

How to event.setCancelled(true); but with a small delay so you can not spam?

lost matrix
#

A good collection type for this is the Deque

willow stream
#

thank you, I will get onto it

lost matrix
# willow stream thank you, I will get onto it

Might not work 100% but you get the idea. getLastMoveVector could also be nicer if you use ArrayDeqeue in the Map because then you would have index access and dont need that re-insertion.

  private final Map<UUID, Deque<Location>> lastLocations = new HashMap<>();

  @EventHandler
  public void onQuit(final PlayerQuitEvent event) {
    this.lastLocations.remove(event.getPlayer().getUniqueId());
  }

  @EventHandler
  public void onMove(final PlayerMoveEvent event) {
    final UUID playerID = event.getPlayer().getUniqueId();
    final Deque<Location> locations = this.lastLocations.computeIfAbsent(playerID, key -> new ArrayDeque<>());
    if (locations.size() == 2) {
      locations.poll();
    }
    locations.add(event.getTo());
  }

  public Vector getLastMoveVector(final UUID playerID) {
    final Deque<Location> locations = this.lastLocations.get(playerID);
    if (locations == null) {
      return null;
    }
    final Location last = locations.poll();
    final Location secondLast = locations.poll();
    final Vector vector = last.toVector().subtract(secondLast.toVector());
    locations.add(last);
    locations.add(secondLast);
    return vector;
  }
willow stream
#

holy, thank you for providing this

grim ice
#

which shouldnt be done async?

#

or am i missing something

young knoll
#

You can do some stuff async

#

But if you need to ask what, you probably aren’t ready :p

maiden briar
#

"SELECT * FROM {table} WHERE player_uuid = '" + uuid.toString() + "'"
java.sql.SQLException: Invalid utf8mb4 character string: 'ACED00' ?? How is a UUID not utf8?

lost matrix
#

use prepared statements

tardy delta
#

please use ?'s

young knoll
#

Prepared statements plz

maiden briar
#

Doesn't work either

dusky sky
#

can anyone provide a worledt plugin for 1.8.9 which can load a heavy schematic

young knoll
#

McEdit

grand venture
tardy delta
#

1.8.9 😳

tardy delta
lost matrix
tardy delta
#

you can use cooldowns maybe depending on what you're doin

young knoll
#

Yeah I would use a simple map with a time stamp (long)

grand venture
tardy delta
#

smh

#

return

#

there is something as !=

grim ice
#

actually

#

return better

#

probably

#

looks cleaner imo

willow stream
grim ice
willow stream
grim ice
#
    @EventHandler
    public void onBlockBreak(BlockBreakEvent event) {
        if(event.getPlayer().getGameMode() == GameMode.CREATIVE)) return;

        event.setCancelled(true);
    }``` @grand venture
#

u cant delay cancelling an event

tardy delta
#

if(event.getPlayer().getGameMode() != GameMode.CREATIVE)) event.setCancelled(true) 🤡

grim ice
#

as the event wouldve already happened

tardy delta
#

i died

lost matrix
#
        if(event.getPlayer().getGameMode() == GameMode.CREATIVE)) {
          return;
        }

pls 😄

tardy delta
#

lol

#

🥲

young knoll
#

I don’t really like using {} just for a return

quiet ice
young knoll
#

Think of the lines you can save

lost matrix
tardy delta
#

i always use {} except for returns

quiet ice
#

I mean, if I have a rule I'd (in theory) apply to everywhere and not have nigh-useless exceptions

ivory sleet
#

Google style guide uses 2 space indents 👀

young knoll
#

Heck google

#

I use 7 spaces

hasty prawn
#

I use new lines

quiet ice
#

Meanwhile intelliJ-decompiler uses 3 spaces by default

ivory sleet
#

Yeah, wish there actually were some sort of convention for this

#

Apart from obviously not having 0

quiet ice
#

I guess tabs could be it?

ivory sleet
#

Myeah, to some extent that’s probably as good as it gets

tardy delta
#

having 0 spaces as indent 🤡

young knoll
#

/* this is an indent */

tardy delta
#

/* this is a ||cow 🐮|| */

ivory sleet
tardy delta
#

/* this is a ||conclure uwu|| */

ivory sleet
#

yeaa

young knoll
#

If you can’t handle me at my OwO
Then you don’t deserve me at my UwU

ivory sleet
#

Man I have some serious issues figuring out how I should structure data. In a SQL DB I could have 1 table per currency, or I could have 1 table with all the currencies. Same issue for banks. If anyone has any insight they want to supply I'd gladly appreciate it lol.

PS should be said, I will be implementing a similar flat file system, so the same data model goes for that as well.

tardy delta
#

why not one table for currencies?

#

and store them all there

ivory sleet
#

Idk

#

like lets say I only want to load a specific currency balance of a user

lost matrix
ivory sleet
#

then it would be pretty much not possible

tardy delta
#

i would store a foreign key to the currency id for the user

ivory sleet
#

yeah

#

well that'd still result in multiple tables

tardy delta
#

so a table with user ids and currency ids in a table, amount might be there too

young knoll
ivory sleet
#

ah

lost matrix
#

I think one table per currency would be the most relational approach

ivory sleet
#

yeah

young knoll
#

You want my giant book called “SQL queries for mere mortals?”

tardy delta
#

i just had database design lesson in school duke

lost matrix
#

You could also use an orm and dont worry about it

tardy delta
#

im just seeing a currency and an user as two different entities

ivory sleet
#

Yes

tardy delta
#

thats alot of yea

ivory sleet
#

well this data model is abit excruciating

#

but ye

neon minnow
#

How to disable /ver /version /bukkit:ver and /bukkit:version, because when i try to make it my own command it still works and shows the version.

#

thanks

quiet ice
#

commands.yml

lost matrix
lost matrix
elfin atlas
#
public void setEqupiment(EnumWrappers.ItemSlot slot, ItemStack item) {
        this.equipment.add(new Pair<>(slot, item));

    }
public final List<Pair<EnumWrappers.ItemSlot, ItemStack>> equipment;
this.equipment = Lists.newArrayList();
  if(this.equipment.size() > 0) {
            PacketContainer packettt = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
            packett.getIntegers().write(0, this.entityId);
            packett.getSlotStackPairLists().write(0, equipment);
            main.protocolManager.sendServerPacket(viewer, packettt);
        }

This is what I'm doing

neon minnow
tardy delta
#

isnt there a getBuffer method in it?

#

getMessage

olive lance
#

is PlayerTeleportEvent only for going through nether portals? Or will other plugins also cause that to fire when teleporting players

young knoll
#

Yes they will

#

Also enderpearls

#

Etc

olive lance
#

Ty

#

TeleportCause.PLUGIN and .COMMAND - Could it be both?

pearl bloom
neon minnow
#

How do i remove spigot/bukkit commands from / <tab>

tardy delta
#

playertabcomplete event

#

ah without the player

willow stream
olive lance
#

Im assuming teleportcause.Command is only when a vanilla command causes the teleport? is that true or not

tardy delta
#

is a weakreference to store something, but make it able to be gc'd when possible?

#

or something

neon minnow
tardy delta
#

you can modify the completions i guess

eternal oxide
#

the command map is sent at login and other times. remove permissions for teh commands you don;t want players to see

tardy delta
#

its not an immutable list

young knoll
#

There’s an event for it

#

PlayerCommandSendEvent

eternal oxide
#

He is talkign about commands not tab completion

tardy delta
#

he wants to hide it

eternal oxide
#

to control what commands are seen is controled by permissions

young knoll
#

Remove them from there

eternal oxide
#

^ that too

neon minnow
#

but on a / <tab>

tardy delta
#

they wont show up if you dont have permission to use them

#

forgot that

neon minnow
young knoll
#

Then remove them

#

From that event

neon minnow
#

How?

#

I want to be able to allow tab completion inside of commands but not on / <tab>

#

How do you cancel it

#

you cant

eternal oxide
neon minnow
eternal oxide
#

You are talkign about the wrong event

#

try listening

neon minnow
#

I dont have PlayerCommandSendEvent

#

Unresolved reference.

eternal oxide
#

commands that are shown in / <TAB> are controled via permissions. Ones which are not YOU remove in the PlayerCommandSendEvent

#

update your Spigot

neon minnow
young knoll
#

Ah 1.8

eternal oxide
#

Then you are out of luck, unless you use reflection and modify the command map

young knoll
#

No idea, I think the tab complete event fires for base commands back then

#

Doesn’t matter tho, we don’t support 1.8

quiet ice
neon minnow
#

fixed w/ PlayerChatTabCompleteEvent

neon minnow
#

so....

supple elk
#

What version of Java do I use? Is it java 8 for anything below 1.18 then java 17 for 1.18?

young knoll
#

1.17 used 16

ancient jackal
#

I keep getting this error Could not pass event PlayerJoinEvent to AltAlerter v1.15-SNAPSHOT org.bukkit.event.EventException: null
that is caused by java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.Object java.lang.ref.Reference.referent accessible: module java.base does not "opens java.lang.ref" to unnamed module @8506a43

Here is the code that uses Gson https://paste.md-5.net/nagoquyugi.java
Here is the error in full https://paste.md-5.net/ubeloxumok.cs
I use the Gson that comes with Minecraft, 2.8.8

sterile token
#

if your plugin will be compatible with version 1.8x and up (except the last version) i would use java 8 base

ancient jackal
#

what spam?

sterile token
#

Oh sorry i confuse you with another man that was spamming for help

#

My fault

supple elk
#

for 1.18.1

sterile token
#

For 1.18x i would use the last Java version, prob java 17

supple elk
#

👍

#

ty

sterile token
#

Your welcome, im not profesional but i try to do my best helping

lost matrix
lost matrix
#

InetAddress needs a custom serializer to be registered

sterile token
#

Lmao i love networking i touched smth on my bedroom router and now the pages are not loaded

#

Hahaha i will have be entreteined today

ancient jackal
eternal night
#

Does GSON by now already ship an inbuild UUID adapter ?

ivory sleet
#

iiirc yes

eternal night
#

I mean, player is also not serializable by default

#

ah nice

sterile token
grim ice
#

wait thats an old message

ivory sleet
#

😛

eternal night
#

Eyyyy

#

and gson does that

ivory sleet
#

very pog

sterile token
#

Now you sent that, why you cannot save uuid? If it a simple string

#

🤔

midnight shore
#

Hi guys! i want to make armor stand pets (like the hypixel skyblock ones) but i don't know how to make it follow the player

hybrid spoke
#

maybe an upcoming lib can help (cought @opal juniper)

tardy delta
#

PathFinderGoalFollowEntity?

opal juniper
#

yes that

hybrid spoke
tardy delta
#

i dunno

opal juniper
#

oh i didnt read it

#

that wont work no

neon minnow
#

is md5 the only spigot dev

opal juniper
#

there are many contributers

#

however, i would consider the only main one yes

stray crescent
#

@opal juniper you a good java programmer?

opal juniper
#

Im ok yes

stray crescent
#

yoo

#

i have a proposal

#

pls lemme call u on vc

#

lets just have a chill chat real quick

#

@opal juniper

hybrid spoke
opal juniper
red sedge
#

how can the itemmeta of an item be null?

#

if the item is not air/null

young knoll
#

It can’t

neon minnow
#

I cant seem to block the /version command, im trying to add a /version command but it does not override it

young knoll
#

Just remove the perm?

tardy delta
#

how can i prevent the database call to load a player not being finished when the player joins?

young knoll
#

If you call it in the APPLE it should block login until it’s done

tardy delta
#

ye but some people said to not load stuff in that event

#

and im also checking the player has played before

#

to either create a new profile or load it

neon minnow
young knoll
#

Negate it with a perm plugin

tardy delta
#

this isnt probably the right time to get an offlineplayer object

young knoll
#

Probably not

sterile token
#

When do you need to use OfflinePlayer object?

young knoll
#

My loadPlayer is able to handle players that don’t exist

tardy delta
#

show me 👀

young knoll
#

It just creates a new user and then attempts to apply the data from the database

#

If there is no data, it just won’t apply anything

tardy delta
#

ah wait i understand

#

so checking if the player has played isnt needed anymore

#

but you can end up with some unneccessary db calls?

sterile token
#

That why i work over cache

young knoll
#

I mean it’ll still do a database call and just return nothing

#

But meh, it’s async anyway

tardy delta
#

it takes time 💀

sterile token
#
  1. OnPlayerJoin -> Check cache
  2. If player exists on database, load it to cache
  3. If data doesnt exists on database, create his cache
  4. OnPlayerQuit -> Save cache to db
tardy delta
#

shouldnt i load on login?

sterile token
#

Send full code

#

So we can understand

young knoll
#

Only saving on quit, oof

tardy delta
#

i dont have any code yet for loading

sterile token
sterile token
young knoll
#

Save regularly

#

Crashes exist

sterile token
#

When server crashes should disable each plugin, so the cache save everything to db?

tardy delta
#

i was thinking about loading the player in login instead of join but the login event might be cancelled so i can end up with some unneccesary db calls i guess

#

idk if join is going to load it quickly enough

#

and idk if its blocking

eternal night
#

it is

tardy delta
#

but the db call is async

eternal night
#

but one unnecessary db call isn't too bad

sterile token
eternal night
#

no a statement

tardy delta
#

i can use a CompletableFuture::join but ye

blazing scarab
#

i save my data when it gets modified

ivory sleet
#

^

sterile token
eternal night
#

We also have periodical storage

#

we flag data dirty

ivory sleet
#

usually you wanna save when a set of modifications have been applied verano

eternal night
#

and flush to DB every ehhh 5 mins ?

ivory sleet
#

else you're risking a data loss

neon minnow
#

if (command == "version") { e.isCancelled = true }

this doesnt block version command

blazing scarab
#

that required some overcompliation so we did some sort of bulk saves system (aka editors)

eternal night
#

string comparison with ==

sterile token
ivory sleet
#

if the server crashes

#

as you mentioned lol

eternal night
#

Depends a lot on the crash if your plugin still gets the onDisable

sterile token
#

I have tried many to do a data loss and i couldnt do it

tardy delta
#

lmao

eternal night
#

oh eyyy conclure

warm mica
#

God do I hate spigot's config API. You can't expect it to work reliable. I hope they improved it in newer versions

tardy delta
#

diskord

eternal night
#

someone for you @ivory sleet

tardy delta
#

what would that be diskord

#

🤔

warm mica
#

Don't click on it! This is a scam

tardy delta
sterile token
#

I was told on a thread that if spigot server crashes or goes down by stop command each plugin is disable, so onDisable method it called

warm mica
tardy delta
#

System.exit(0)

sterile token
tardy delta
#

idk

ivory sleet
sterile token
#

Because its get cleared

ivory sleet
#

what message?

sterile token
ivory sleet
#

oh

#

someone else banned em probs

tardy delta
#

he was even verified lol

sterile token
#

I think that you can be banned from Website right? Or i am wrong¿?

tardy delta
#

im just thinking whyy

sterile token
vale cradle
sterile token
olive lance
tardy delta
vale cradle
sterile token
#

So i dont know

tardy delta
#

it gets handled when closing it

opal juniper
#

So if i have an API module that the users are able to depend on, and then i wanted to make the lib shadeable, how would i do that? atm i keep only the API available to the users to depend on but i wanted to try and have it shadeable rather than just a plugin lib

olive lance
#

Ty Coll for the feedback

sterile token
#

And something more dangerous, doing a vps reboot with the server screen opened, and server data steal saved

vale cradle
#

it forces to stop a program running on a console

warm mica
vale cradle
#

anyways, it's not possible for you to handle all of those exceptional cases (I say it by experience working on a similar system), sometimes you just have to deal with it

young knoll
#

Imagine if the server somehow always ran onDisable

#

Pull the power cord? Nah it’s fine

vale cradle
#

saving every x time is what works the best, but make sure your db can handle that (and use batch statements)

sterile token
opal juniper
#

Thats not what i mean

sterile token
opal juniper
#

other people only have access to the API module, where i then have another module that impl's that which runs on the server. because of this i was wondering if it is possible to shade it

young knoll
#

I just save on every change

sterile token
charred echo
#

@opal juniper mvn install

tardy delta
#

idk 🐗

charred echo
#

then import it

sterile token
charred echo
young knoll
#

This is why we have sql

dusk flicker
#

I save on every change with mongo

#

Never had a problem

opal juniper
charred echo
#

jitpack

sterile token
opal juniper
#

yes that is how you would host the API, but that isnt what i mean

dusk flicker
#

🤨

charred echo
#

🤔 what do you mean then

sterile token
#

I use Mongo + ORM and best thing ever created

young knoll
#

Yeah saving on every change on mongo should still be fine

#

It’s a database, it’s kinda designed for that

dusk flicker
#

If you're having a problem with that you've just designed it wrong

opal juniper
# charred echo 🤔 what do you mean then

There is a public API module that will be hosted online and users can depend and dev against. Currently, i then have a module that impl's the API and runs as a plugin dependency on the server. This is annoying tho and so i was wondering if there was a way for the users to shade the "main" without the impl being with the API

young knoll
#

I have a connection pool and a dedicated thread pool for saving

#

I don’t think it will cause issues unless you try to run it on a server with thousands of players

velvet dragon
#
public class Database implements Serializable {

    @Serial
    private static transient final long serialVersionUID = -1681012206529286330L;

    public static final String filePath = "database.ser";

    private ItemStack[] activeItems;
    private ItemStack[] collectedItems;
    private ItemStack[] disabledItems;
    String name = "Test";
    ...
    public boolean saveData(String filePath) {
        Bukkit.getServer().getLogger().log(Level.INFO, "Trying to save...");
        try {
            FileOutputStream fileOut = new FileOutputStream(filePath);
            BukkitObjectOutputStream out = new BukkitObjectOutputStream(fileOut);
            out.writeObject(this);
            out.close();
            Bukkit.getServer().getLogger().log(Level.INFO, "Data saved!");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            Bukkit.getServer().getLogger().log(Level.INFO, "!SAVING FAILED!");
            return false;
        }
    }
    ...
}

Hey,
im trying to save the entire Database Class with the active,collected and disabledItems arrays into a file. Is this the right way to go about it? Its loosely based on this https://www.spigotmc.org/wiki/save-load-data-files/
If i save the data this way no file gets created :/ Does anyone see why ?

tardy delta
#

aa

vale cradle
sterile token
warm mica
#

How is it possible that config.get("data", null) always returns null, and config.get("data") only returns null when there's actually none. Ffs spigot

charred echo
#

so basically a wrapper for your api

#

that prople could use a dependency that just calls ur api

sterile token
velvet dragon
#

Sorry for interrupting this chat ^^

tardy delta
#

you scared me

sterile token
#

Because the meaning of API keyword for spigot most of time its a jar dependency that allow you to get data.

#

And for other people its just to use it in paralel with a Rest API

young knoll
vale cradle
sterile token
#

My first work when started was to make an api based on Rest API. So basically i was connecting their custom rest api to a plugin on multi servers

velvet dragon
#

Saving Data to File Problem

tardy delta
#

is the playerjoin event blocking for database stuff on a completablefuture?

opal juniper
#

well

#

the whole thing about a CF is that it isnt blocking

#

but playerjoinevent

#

is

#

blocking, but players can time out

tardy delta
#

yea im trying to block the player from joining until data is loaded

opal juniper
#

start the request on the pre login event

eternal night
#

player join event is on the main thread

#

pls don't block it

opal juniper
#

but yes

#

what lynx said

#

thats terrible

tardy delta
#

so starting on asyncprelogin?

opal juniper
#

yes

#

its probably done by the time they are in anyways

tardy delta
#

players might be disallowed from joining later on

#

but ye

#

could end up with a unneccesary request but thats the least i have to worry about i think

#

also async and CompletableFuture::join might that give problems?

eternal night
#

a single request to a database that selects a single record that is properly indexed on the key is not an issue

tardy delta
#

but a completablefuture is async and the event is also async

#

so no problems?

eternal night
#

Ye

vale cradle
#

yes, np

ivory sleet
#

FourteenBrush

#

join makes it sorta sync

tardy delta
#

ye

#

halts the current thread right?

ivory sleet
#

since it makes the code execution order predictable in a way

#

mhm

tardy delta
#

lemme write some code

vale cradle
#

it's pretty much resume right after the cf was completed

#

returning their result

tardy delta
#

me and concurrency is asking for problems

ivory sleet
#

well concurrency is a bitch and atomicity is just horrific

vale cradle
#

also, if you can avoid using join, do it, because joining I guess merges the threads (or something similar idk what's called) and it's kinda expensive operation. Try using the thenAccept, thenApply, thenCompose & whenComplete methods the CF class provides you

tardy delta
#

you said something earlier about the user and the snapshot remember?

ivory sleet
#

yes that was just to avoid mutability as much as possible

#

to avoid concurrency update problems

tardy delta
#

so i would only load the snapshot as it holds the data?

ivory sleet
#

well

#

I mean

#

its just as having a set of accessors and mutators

#

however

tardy delta
#

and fields

ivory sleet
#

you do it a bit differently

vale cradle
#

if you want the object just to be mutable when it's loaded you can try using a CountDownLatch btw (very useful class)

minor fox
#

Are the fields in classes like EntityLiving explained somewhere?

opal juniper
#

No

#

Thats nms code

ivory sleet
#

mye cdl, semaphores, cyclicbarrier and phaser all amazing framework classes

tardy delta
#

i could load the snapshot and apply it to the user

ivory sleet
#

let me write an example in a moment

#

playing cs rn

tardy delta
#

np

minor fox
#

Does anyone know the default noDamageTicks?

#

(if there is one)

buoyant viper
#

if its what i think it is its probably 10 or something

eternal night
#

Depends on what default

#

Generally 0, players have a 60 tick spawn invulnerablility

opal juniper
#

Hm, So i have a prio queue of node objects. I want to check if it already contains a node at a certain position and if so, get that node. idk really how to "get" from a queue tho as i thought it wasnt possible

buoyant viper
#

ok i liked it might be 20, or between 0 and 20

eternal night
#

20 is after damage

#

ye

#

I mean "default" is a pretty loose concept

buoyant viper
#

if thats even possible

#

might be able to use an iterator() method or something

opal juniper
#

ugh yeah ig, that seems really inneficient tho

#

maybe tho

buoyant viper
#

well i dont think ur meant to have to traverse them

native gate
#

hi, in craftbukkit contributing is said that the changes need to be for java 7, is this actual? or i can make changes for java 17 already?

chrome beacon
#

Sounds like that's outdated

ivory sleet
#

java 8 iirc is what you wanna lean towards iirc Choco mentioned

native gate
buoyant viper
#

id imagine java 8 bc i think 1.8 needed it and thats the earliest? available spigot

#

not that any changes get made to 1.8 still but

opal juniper
wet breach
#

well it would

#

just not the way you think it would

#

if you really need to know if something exists in a queue, you need to give your objects id's

#

and then as you insert into the queue you also keep a list or hashmap of said object id's

#

then when the queue gets to it you know if it needs to do something or just discard it

#

your only option for gettings objects in a queue is to iterate over the queue which probably isn't going to be ideal most times lol

#

unless you implement your own kind of queue to allow this of course

brave trellis
#

So I'm trying to cast TileEntitySkull, however I am getting a 'java.lang.IllegalArgumentException: object is not an instance of declaring class'

"l" being the location of the block and version being "v1_18_R1"

Class<?> clazz = Class.forName("org.bukkit.craftbukkit." + plugin.version.substring(plugin.version.lastIndexOf('.') + 1) + ".CraftWorld");
Class<?> anotherClazz = (Class<?>) clazz.cast(l.getWorld()).getClass().getMethod("getHandle").invoke(clazz);
TileEntitySkull skullTile = (TileEntitySkull) anotherClazz.getMethod("getTileEntity").invoke(new BlockPosition(l.getX(), l.getY(), l.getZ()));

It seems to cause an error on the second line within these 3 lines of code within console

eternal night
#

you are casting the result of getHandle to a class ?

wet breach
#

probably going to need to use blockstate

native gate
sly trout
#

hey guy's I've been trying to save data to a file but I can't do it it doesn't work the file isn't even showing up here is my code: ```
public class ReportsData {

private File _file;
private Gson _gson;
public ReportsData() {
    _file = new File("data.cum");
    try {
        if (_file.createNewFile()) {
            System.out.println("File created: " + _file.getName());
        } else {
            System.out.println("File already exists.");
        }
    } catch (IOException e) {
        System.out.println("An error occurred.");
        e.printStackTrace();
    }
    _gson = new Gson();
}

public void saveToFile(Object object) throws IOException {
    FileWriter fileWriter = new FileWriter(_file);
    String toJson = _gson.toJson(object);
    _gson.toJson(object, fileWriter);
    fileWriter.close();
}

public Object getFromFile() throws FileNotFoundException {
    FileReader fileReader = new FileReader(_file);
    Type type = new TypeToken<ArrayList<Report>>(){}.getType();
    ArrayList<Report> clonedMap = _gson.fromJson(fileReader, type);
    return clonedMap;
}

```
eternal night
#

also for what adoes one still need NMS for skulls in 1.18 ?

#

curious

tardy delta
#

this isnt C#

brave trellis
eternal night
#

spigot released a profile API

#

that can manage custom textures for you

#

it is available in 1.18

#

did anyone write a nice forum tutorial for it yet ?

#

that we could link

brave trellis
#

i figured out how to put it in an itemstack, but not for a block, for a block it was nms

brave trellis
#

so using using block.setData one would change a skull head to a texture?

eternal night
#

what ?

tardy delta
#

something liek this?

eternal night
#

?paste

undone axleBOT
eternal night
#

smh

ivory sleet
#

lol

#

let me fix

tardy delta
#

wait

#

forgot the cf

ivory sleet
eternal night
#

and then update the block state

brave trellis
#

and it was that simple?

tardy delta
#

conclure you forgot a space

brave trellis
#

pain

tardy delta
#

🤡

eternal night
#

Well the API is very new

#

like very new

sour socket
#

Heyo

#

I'm new to Spigot plugin Development

#

Can someone help me figure out how to check if a player broke a certain block

brave trellis
#

blockbreakevent ?

sour socket
#

Yep

#

How can I utilize it?

#

Here, lemme show you my current file

lost matrix
brave trellis
#

event.getBlock() no?

lost matrix
ivory sleet
#

@tardy delta anyhow, both are doable, so I am not gonna tell you to do x or y

#

but the latter is a bit more scalable

sour socket
#
package me.miney.starterobjectives.listeners;

import me.miney.starterobjectives.Main;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;

public class BlockBreakListener implements Listener {

    @SuppressWarnings("unused")
    private Main plugin;

    public BlockBreakListener() {
        this.plugin = plugin;
    }

    private ItemStack dirt = new ItemStack(Material.DIRT,1);

    @EventHandler
    public void onBlockBreak(BlockBreakEvent e) {
        Block block = e.getBlock();
        World world = block.getWorld();
        Player p = e.getPlayer();

        if(Idk what to put here) {
            

        }
        
    }

}

tardy delta
sour socket
brave trellis
#

block.getType() == Material.DIRT

brave trellis
#

or something like that

eternal night
#

cafe babe should just agressively throw every message into a paste that is longer than 5 lines

sour socket
#

Ohh

blazing scarab
#

I wonder

#

Will paper deprecate their player profile api

ivory sleet
tardy delta
#

thank you so much 💗

ivory sleet
#

yeah

sour socket
#

the hell

ivory sleet
#

I can write an example with the cache and database fourteenbrush

tardy delta
#

you can..

#

or you can play your game

#

i'll continue tomorrow probably

sour socket
#

Can someone help me figure out the code to check if a player broke a dirt block?

ivory sleet
#

ah fair then, lets continue tmrw lol

brave trellis
#

.

#

.

#

.

sour socket
#

Didn't work

tardy delta
#

ggood

brave trellis
#

send code

tardy delta
#

🥣

brave trellis
#

yes spoon feeding

tardy delta
#

?main

brave trellis
#

replace "> Idk what to put here" with the little code bit i sent u

tardy delta
#

motivation why you shouldnt call your plugins class Main 🌝

#

doesnt really matter for smoll things but ye

sour socket
#

Best bot on this planet

tardy delta
#

motivation idk how to say it

sour socket
#

OMG @brave trellis TYSMM <3333333

tardy delta
#

love

sour socket
#

Sorry it's been the hell of a day I really shouldn't be coding

sour socket
sour socket
#

🤷

sly trout
#

how do you save a file to the plugin's folder?

young knoll
#

Plugin#getDataFolder for the directory

#

Then you can create a File instance with that

azure imp
#

How can I update a plugin of bedrock?

sly trout
wet breach
vast shale
#

Is there a way to get the type of close in InventoryCloseEvent? I have players added to a HashMap to store the page of the GUI they're on when they open my GUI, then removed on InventoryClose. My only problems is when a new GUI is opened, the InventoryCloseEvent is called, removing the player from the HashMap prematurely

tardy delta
#

i didnt know there were plugins for bedrock

wet breach
vast shale
#

Cause how would it know to add them back? Is the only way to check each inventory's name?

hollow bluff
#

Can’t you just check which inventory was closed and go from there?

#

so it doesnt remove them from the map

wet breach
#

you can compare the inventory objects that are opened and see if its one of yours

#

But also as said above you can check which inventory was closed as well

#

Seems you just need to redesign how you are going about it

vast shale
#

Ah okay, was hoping there was enum like InventoryCloseType.PLUGIN but I'll go with that. Thanks guys

neon minnow
#

Why cant i block the /version command from executing??

#

on PlayerCommandPreprocessEvent event

red sedge
#

just remove the permission

neon minnow
red sedge
#

permission

#

=

#

false

#

luckperms or smth

neon minnow
#

tf

red sedge
# neon minnow tf

remove the permission of /version from the users you dont want to run /version

#

using luckperms or smth idk

neon minnow
#

I dont use permissions anyway...

wet breach
# neon minnow how??

bukkit.commands.(commandname) is generally the permission nodes for such things

neon minnow
wet breach
#

ok not sure what that has to do with perms

neon minnow
#

well im not talking about perms so

wet breach
#

We are

neon minnow
#

only that guy is talking about permissions

#

im talking about the command event.

red sedge
#

they're trying to cancel the version command and it is just far easier to use permissions

#

and that way you wont block some weird ass plugin from overriding it

neon minnow
#

i dont use luckperms, and other addons....

#

weird ass luckperm

wet breach
#

Yes you can use the permissions to block it, not sure why you want to go the hard route on this

neon minnow
#

i aint downloading anything

red sedge
wet breach
#

don't need to

neon minnow
wet breach
#

Well I guess if you want to go a no permissions route, then just check if they are ops o.O

neon minnow
#

I just told you, even made a custom command /version and it did not overrrite the bukkit version command, so i had to use the PlayerCommandPreprocessEvent with "e.message.contains" to cancel it fully

#

it did work in the end so

wet breach
red sedge
#

but that would also prevent a command that contains "ver"

neon minnow
#

yea okay thanks

neon minnow
red sedge
#

sure

wet breach
#

some people just enjoy working harder it seems

#

XD

#

anyways, back to my game

neon minnow
#

No, not hard for me

#

its actually pretty easy and the best way FOR ME

wet breach
#

if you say so, not arguing here. As I said going back to my game

neon minnow
#

Permissions and shit? wtf lol, i just use my own db with my own rank system

red sedge
wet breach
#

World of tanks at the moment

#

got this event going on so I need to ensure to get a few games in everyday

red sedge
#

fair enough

young knoll
wet breach
#

doubt it? World of tanks is basically a FPS but with tanks

neon minnow
wet breach
#

because they are just easy to work with, and easy to use API wise for other things

#

don't necessarily need a permissions plugin to use it either

red sedge
wet breach
#

the API already has built in methods for permission usage

#

if you want to go about it differently and not make use of what the API provides so be it

blazing scarab
#

1.8
professional

red sedge
#

like even hypixel with its millions of dollars still uses citizens

#

which is kind of funny to me but makes sense

wet breach
#

the major problem with everything custom, is maintaining it

red sedge
#

yeah

wet breach
#

the more things that are custom, the more there is to maintain and update yourself

red sedge
#

also like if there is someone else doing it for you

#

why waste time

neon minnow
blazing scarab
#

Yes

red sedge
#

1.8 is 7 years old

neon minnow
#

lol

#

oh no its old, ppl still play it tho

red sedge
#

yeah because people are stupid

#

and also blah blah pvp blah

wet breach
delicate lynx
blazing scarab
#

least of community plays 1.8

neon minnow
red sedge
#

many people play 1.8

wet breach
#

obviously you don't care otherwise you wouldn't use 1.8

red sedge
#

but most of them play on hypixel

#

or other big servers

neon minnow
#

Its fine

red sedge
#

also isnt hypixel on 1.7? like serverwise

wet breach
#

Anyways regardless of the version you are using, the version doesn't dictate anything other then what it is you want to provide

red sedge
#

and implement 1.8 features

wet breach
#

protocol hacks generally suck for the most part

blazing scarab
red sedge
blazing scarab
#

Also, modt of big servers use 1.8 moslty because of their legacy codebase. You have a great chance to use a supported version

red sedge
blazing scarab
red sedge
#

and that just takes a lot of time

#

so unless big servers invest a lot of time they are stuck at 1.8

neon minnow
#

Anyways how do icheck if the item that is placed on the BlockPlaceEvent is a Chest named "test" ?

red sedge
#

getitem

neon minnow
#

No documentation is found

#

you mean

wet breach
#

well its no longer an item if its placed

neon minnow
#

itemInHand

red sedge
#

idk ancient versions

#

not sure if i can help with the older api verisons

neon minnow
#

hm it says
Expression 'CHEST' of type 'Material' cannot be invoked as a function. The function 'invoke()' is not found

if (e.itemInHand == Material.CHEST {
e.isCancelled = true
}

brave sparrow
delicate lynx
#

getBlockPlaced(), get chest inventory, get name

red sedge
#

so basically 1.8 is going to be the version for big servers

#

not the go to for new servers tbh

blazing scarab
#

Old big servers

eternal night
#

I mean, not much preventing you from ViaBachwards 1.18

red sedge
#

and the only reason its the version for old big servers is that they just cant update

#

without updating everything

wet breach
red sedge
#

like pretty sure hypixels owner said they were planning to update to 1.16 before but couldnt because they would need to update everything

neat trellis
#

Is there a way to heal a player and it to play the animation(?) of the hearts flashing?

red sedge
glossy venture
wet breach
#

as I keep saying you can't expect to get enterprise software for free just because you want it

neat trellis
glossy venture
#

higher regeneration effect = faster animation

#

i think

red sedge
#

wait no

glossy venture
#

thats what i mean

red sedge
#

the animation isnt based on packets i dont think

neon minnow
#

I know how to check item in hand

        if (e.itemInHand == Material.CHEST) {

But how do i check the name of the item ?

neat trellis
#

packets would work i think

red sedge
glossy venture
#

on the client side

neon minnow
glossy venture
#

so using packets to give someone regen but only on their side

#

will probably play it

red sedge
red sedge
#

getItemMeta()#getDisplayName()

glossy venture
#

if you dont want them to heal all the way or something

#

and it will only be visible for them

red sedge
#

or well you can store their health in a custom value and send that every tick

#

but i think the client side regen effect might be glitchy

#

for players with high ping especially

blazing scarab
#

I dont see the point of hiding healing process to others

neon minnow
glossy venture
#

but thats not what he asked

#

just how to play animation

eternal night
#

that animation sounds pretty client side

blazing scarab
#

"heal player and play animation",no?

glossy venture
#

yeah

next stratus
#

What's better to use isBlock or isSolid? I wanna make sure the block passed through a map is a valid block for going in a cuboid region

eternal night
#

I mean

#

two different things

red sedge
glossy venture
next stratus
#

so is it best to use isBlock then?

glossy venture
#

i guess

blazing scarab
#

Ehats the point

next stratus
#

I just wanna make sure no blocks like Grass go through, etc..

red sedge
eternal night
#

grass is a block tho

glossy venture
eternal night
#

^^

red sedge
#

why is everything in variables

neon minnow
blazing scarab
#

Thats dumb kotlin

next stratus
#

i swear intellij fucking hates me today

blazing scarab
#

Taking getters and setters too much seriously

next stratus
#

suddenly it's crashed like 3 times

red sedge
tall nova
#

Does the ChannelPipeline for a player close when they disconnect? Or is my deregister for my ChannelDuplexHandler actually useful?

red sedge
#

every update it gets worse tbh

next stratus
#

i've had 0 issues with it for ages

eternal night
#

^^

#

I don't think it is the updates

next stratus
#

like i use it daily and today it's like "ha gonna take a shit on you"

dusk flicker
#

ive never had issues with intellij

next stratus
#

I'm gonna print a logo off and rip it up

dusk flicker
#

but every programmer has those days lol

next stratus
#

that'll make me feel better

red sedge
#

it is very much the updatess

eternal night
#

Okay dude 👍

red sedge
#

sometimes intellij cant import settings after an update and you have to remake the project so it will make the new settings becuase if you dont you cant see anything in the project view

#

and blah blah blah

dusk flicker
#

ive been using intellij for years

#

never once have had to do that

eternal night
#

^^ I store my settings in a settings repo

#

works great

dusk flicker
#

I dont do anything for settings lol

#

it just works

neat trellis
# red sedge packets?
PacketContainer packet = new PacketContainer(PacketType.Play.Server.UPDATE_HEALTH);
double healAmout = Math.min(Objects.requireNonNull(player.getAttribute(Attribute.GENERIC_MAX_HEALTH)).getDefaultValue(),player.getHealth() + 1);
packet.getFloat().write(0, (float)healAmout);
packet.getIntegers().write(0,20);
try {
    ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
} catch (Exception e) {
    e.printStackTrace();
}
player.setHealth(healAmout);
#

let me know if something ridiculously wrong is here

dusk flicker
#

why do you need to use packets for setting health

neat trellis
#

to play the animation

red sedge
neat trellis
#

yes

red sedge
#

if so lemme just check it in intellij

blazing scarab
#

just use the regeneration effect..

red sedge
blazing scarab
#

Ehat custom healing

red sedge
#

custom healing

#

thats it

eternal night
#

how does that packet trigger regeneration like animations ?

blazing scarab
#

i cant imagine anything rather than just a regeneration effect

red sedge
eternal night
#

that is the same packet used by the server if the health data is dirty

young knoll
#

What animation are we talking about

red sedge
#

the tilty hearts

neat trellis
#

where the outline flashes white

ancient jackal
neat trellis
young knoll
#

Does the client not just play that animation any time the players health goes up

neat trellis
#

with player.setHealth() the animation does not play

dusk flicker
#

you really should be naming your vars better, and following conventions for file naming

#

?conventions

undone axleBOT
red sedge
#

is there an addHealth function?

#

prob not

dusk flicker
#

It might be that you need to put refreshPis after the t = playerinfo, as the refresh method uses T

eternal night
#

Are you resetting your file reader

#

no

#

besides that I would actively suggest to not store a file reader

#

open the file when required

#

instead of keeping a file reader alive the entire time

ivory sleet
#

never nice when you run out of file descriptors

eternal night
#

also in regards to the animation thing, paper has API for it :>

#

but I digress

red sedge
#

you can prob just copy that one method

woeful crescent
#

How would i listen for any time a player is sent someone's equipment with protocollib?

red sedge
#

instead of you know using paper

eternal night
#

ah yes, copy licenced code 🙏

red sedge
young knoll
#

It’s either MIT or GPL

#

So

eternal night
#

True

red sedge
#

GNU

eternal night
#

wat

eternal night
#

bruh

#

bumping after less than a minute

#

xD

blazing scarab
woeful crescent
#

yea

red sedge
woeful crescent
#

just wondering if there was another packet that sent that

#

like one that sent all the entities data at once

#

just new to this generally so

eternal night
#

or just use paper :>

red sedge
#

paper is painful

eternal night
#

Yea you are fine with just the equipment packet

blazing scarab
#

How is paper painful

eternal night
#

the packet will contain all equipment at the start

red sedge
#

adventure api is painful

eternal night
#

so you will have to iterate

#

LOL

blazing scarab
#

Better than legacy crap

red sedge
#

still paper is painful

eternal night
#

We all hate those performance improvements smh

red sedge
#

yes very much

#

performance? nah

#

idk i just dont see the point in using paper just to use 1-2 functions from it

blazing scarab
#

Some functions may be well implemented on kernel side only

woeful crescent
#

you mean multiple right

eternal night
#

no the packet holds a map

woeful crescent
#

seriously?

eternal night
#

yes

blazing scarab
#

paper guaranties version compatibility, using packets not

eternal night
#

or a list of pairs

red sedge
#

im not willing to die on this hill but paper just feels more

#

um

eternal night
#

one of them

red sedge
#

how can i say this

#

annoying

woeful crescent
#

one sec

eternal night
#

pointless discussion I guess

#

if you want to stick to packets

#

the equipment packet contains a list of Pair<EquipmentSlot, ItemStack>

red sedge
#

why do you need equipment packets?

young knoll
#

Using a respected lib also guarantees version compatibility

woeful crescent
#

*with armor

young knoll
#

Isn’t there api for that

woeful crescent
#

idc

#

i've already made it haha

red sedge
#

sure?

woeful crescent
#

i mean like

#

it'll refresh when the player is rerendered tho

#

this is just better

#

plus it doesn't matter im pretty much done

eternal night
#

idk

#

this is what I am looking at in 1.18

woeful crescent
#

interesting

#

idk

#

yeeep it's different in 1.18

eternal night
#

Efficiency

dusk flicker
#

pr it

blazing scarab
#

With this kind of api so many packet-based code can be avoided

young knoll
#

I mean

#

You can hide entities

blazing scarab
#

yeah that's amazing too

keen basin
#

[23:28:53] [Server thread/ERROR]: Could not load 'plugins\Shop.jar' in folder 'plugins'
org.bukkit.plugin.InvalidPluginException: Cannot find main class `me.ag4.shop.main.Main'
Caused by: java.lang.ClassNotFoundException: me.ag4.shop.main.Main
at java.net.URLClassLoader.findClass(URLClassLoader.java:471) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:167) ~[server.jar:2991-Spigot-018b9a0-f3f3094]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:96) ~[server.jar:2991-Spigot-018b9a0-f3f3094]
at java.lang.ClassLoader.loadClass(ClassLoader.java:588) ~[?:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[?:?]
at java.lang.Class.forName0(Native Method) ~[?:?]
at java.lang.Class.forName(Class.java:398) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.<init>(PluginClassLoader.java:64) ~[server.jar:2991-Spigot-018b9a0-f3f3094]
... 16 more

plugin.yml

name: Shop
version: ${project.version}
main: me.ag4.shop.main.Main
api-version: 1.16
authors: [ AG4 ]
description: Shop plugin

commands:
shop:

#

what is the reason ?

dusk flicker
#

2nd line

#

your main class isn't at me.ag4.shop.main.Main

#

and while we are on the topic of main classes

#

?main

woeful crescent
#

how do i prevent an explosion from breaking blocks?

#

anyone

#

nvm

young knoll
#

Remove the blocks from event#blockList

woeful crescent
#

?

#

what about setting breakblocks to false

#

in the createExplosion method?

young knoll
#

That works too

eternal night
#

well either you want a server spawned explosion to not break blocks -> use coll's method

#

or you spawn it and have control over it yourself

woeful crescent
#

oh yeah

#

that's what i meant

woeful crescent
#

if i set the amplifier param to 0, is the potion effect lvl 1?

young knoll
#

Yes

neon minnow
#

how to remove all potion effects off player ?

#

ty

dusk flicker
wet breach
full forge
#

when PlayerAdvancementDoneEvent is triggered, i get both regular advancements (like "Hot Stuff") and recipes ("Fishy has completed the advancement Decorations/jungle Sign"). is there a way to filter it out to not recipes?

young knoll
#

Check the key

#

It may always contain recipe

brave trellis
#

The exception java.lang.NoSuchMethodError: 'net.minecraft.world.level.block.entity.TileEntity net.minecraft.server.level.WorldServer.getTileEntity(net.minecraft.core.BlockPosition)'
occurs

"l" being the location, anyone know why this error is occurring?

Class<?> clazz = Class.forName("org.bukkit.craftbukkit." + plugin.version.substring(plugin.version.lastIndexOf('.') + 1) + ".CraftWorld");
Object testClazz = clazz.cast(l.getWorld());
WorldServer worldServer = (WorldServer) testClazz.getClass().getMethod("getHandle").invoke(testClazz);
TileEntitySkull skullTile = (TileEntitySkull) worldServer.getTileEntity(new BlockPosition(l.getX(), l.getY(), l.getZ()));
#

plugin.version.substring(plugin.version.lastIndexOf('.') + 1) | being the v1_18_R1

young knoll
#

Are you remapping

brave trellis
#

just trying to place a skull block with a texture

young knoll
#

Okay

#

But are you remapping

sullen marlin
#

You don't need nms for this

brave trellis
brave trellis
#

I feel like an idiot, i've been digging through the code of mc for days now trying to find a solution

young knoll
#

That looks like mojmap, you need to remap using maven special source to convert it back to obfus

young knoll
#

Yo we got the player profile API

#

Awesome

brave trellis
#

wait is that for 1.18 only, and not for 1.17?

young knoll
#

Yes

brave trellis
#

agh im gonna go jump off a cliff

#

Thank you md_5 i shall go update now

young knoll
#

Also I see a future in there

#

Which means the API acknowledges futures

#

Now we must make a future version of unloadWorld

neon minnow
#

I am using this (https://www.spigotmc.org/wiki/creating-a-gui-inventory/) to create my own inventory, is there an easy way to add onto it, on click? so it would do a certain action, such as "print hello", just like in skript w/ TuSke ?

Skript example:

format gui slot x with x named x to run:
(print player clicked this!)

Because right now i handle that with a fun onInventoryClick(e: InventoryClickEvent) { }

but i imagine it will be very big as items start to get more and more, as well as this it is a pain, say for example I want to loop players skulls into a inventory, id have to in the inventory click event specify the item name and check what it is to do the certain action

young knoll
#

Use one of the libs on that page

#

They probably support it

warm mica
ebon arrow
#

Skript*

warm mica
#

When done properly you are ae to save lots of time and hussle creating the guis

quaint mantle
#

Please help me

#

Please

#

Someone needs to help me

ebon arrow
#

?ask

undone axleBOT
#

If you have a question, please just ask it. Don't look for staff or topic experts. Don't ask to ask or ask if people are awake or available. Just ask the question to the channel straight out, and wait patiently for a reply. Make sure you use the right channel regarding the topic of your question. Create a thread in case the channel is already in use!

warm mica
ebon arrow
quaint mantle
#

No so basically I'm using essentials bukkit plugin

#

And it normally wormed

#

Worked

young knoll
quaint mantle
#

This has help in the name

ebon arrow
#

For development

warm mica
ebon arrow
#

Like coding

neon minnow
neon minnow
young knoll
#

I would just use an inventory framework

#

I don’t know what this talk about putting a player in a map is

warm mica
#

I wrote this quickly on my phone, but you should get the idea

neon minnow
#

Thank you

#

and so that is way more optimized then my method

warm mica
#

You could add a list or an other map into your info object with all the gui itrms