#development

1 messages ยท Page 75 of 1

worn jasper
#

yes, but uuid IS an id.

#

there is legit no way to update an uuid of an account

#

it's the unique for each account.

graceful citrus
#

updating on other tables has nothing to do with data type

dense galleon
#

How much will the performance be impacted realistically lol

worn jasper
#

the single case where that could be used, is if you want to transfer everything from x to y, but at that point just copy it, create a new user and delete the old....

graceful citrus
#

you mark uuid as foreign or primary key and its no different

graceful citrus
#

on a minecraft plugin basically none

worn jasper
#

I am speaking in the context we are now.

graceful citrus
#

regardless there no point doing premature optimization

worn jasper
#

^^

dense galleon
#

I always fall for the premature optimization trap

worn jasper
#

literally, we are not speaking about a company with millions of rows in an sql database

dense galleon
#

To make "things more future-proof"

graceful citrus
#

take a look here @dense galleon

worn jasper
#

and using uuid or id as primary key, will probably be one of the "less" factors when it comes to optimization in sql

graceful citrus
#

comment by grzegorz

worn jasper
#

since most of the time, it's a query issue

#

take hangar sql queries as an example, they quite need to be optimized, tbf they have already been a bit but not perfect yet

#

and tbh, "norms" can be taken in several ways

#

take hangar again as an example, if you scheck their database structure

#

god...

#

they are not respecting several normal forms

#

lol

#

but to be fair, it wouldn't make sense for them to respect them in their case.

#

normal forms are good to know in general and a good base, but there are cases where they are not good.

graceful citrus
#

main difference would be on index size and you cant get out of querying for the uuid varchar at least once

worn jasper
#

going by id is possible sure, but you would have to do at least one query to get that id with the uuid.

abstract current
#

hi

graceful citrus
abstract current
#

can somebody maybe help me with the connect feature of deluxemenus?

graceful citrus
#

then it might be (probably not) worth it to query for it to get id once then use the id on a id-indexed table

worn jasper
graceful citrus
#

ya exactly

worn jasper
#

will it make a huge difference? maybe in hypixel, but not in 99.99999% of the cases

graceful citrus
#

even in hypixel its probably not a huge difference

worn jasper
#

yeah

graceful citrus
#

but indexing file size wise it will since varchar index is quite size intensive

#

afaik

worn jasper
#

so the question is, do you want to "over" optimize it at the cost of a tiny bit of ram or not lmao

worn jasper
#

TLDR; it does make a tiny difference. Is it that noticeable? Very probably not.

#

Then it also depends on how your systems works, for instance, if you request all the data from the database on join and cache it all, then going with uuid probably won't make a difference.

worn jasper
graceful citrus
worn jasper
#

^^

#

Also, if you care about performance, don't make the mistake some do cause it looks easier of using FROM several tables and then having a WHERE with their conditions, use (inner) joins, they are more performant.

#

And this, funnily enough, can have a huge impact in performance depending on your database from tests I did at school.

abstract current
worn jasper
grand island
#

that just overcomplicating a database schema IMO

#

like now, to insert something for a new player you need to requests its generated id

#

from the database

atomic trail
#

TriumphGui doesn't have a pane system right? To have sub-guis essentially

I'm trying to set up pages for a selection system basically. But not sure what the best option would be

#

@pulsar ferry Sorry for the @ just saw you were online so I hope its fine

pulsar ferry
atomic trail
pulsar ferry
#

Will probably be hard to replicate the same thing, good luck :')

atomic trail
#

I'll use TriumphGui and try to setup a system for the pages, it's just not very easy to handle properly imo

#

TriumphGui already has most of the functionality required actually. The filler basically works like a pane, just configured a bit. It already handles the area functionality

#

Wait Paginated GUI exists? lol

#

Didn't know that

worn jasper
#

lol

atomic trail
#

I can't remember, does the rows start at 0 or 1?

#

when using setItem etc.

worn jasper
#

actually

#

maybe 1?

#

idk

#

try and see I suppose?

atomic trail
#

Ye same lol

#

I'll test, just gotta make this compilable first

worn jasper
#

I have it somewhere but too lazy to open intellij

#

just go to the method's code

#

and check it

atomic trail
#

True

hollow barn
#

on shoot:
if projectile is an arrow:
send "You Have Thrown A Pass!" to shooter
on projectile hit:
victim is a player
send "you have completed a pass" to shooter
okay so i have this but i want it to then wait until the victim is hit and then track the north and south amount from the shot to the hit and display that and im super confused on how to do that
im trying to transfer this from skript to a plugin how i do

graceful citrus
#

listen to entity damage by entity event

#

then check for damager type, cast to arrow if arrow

#

then get shooter of the arrow for the second part

#

for first part you need this one

worn jasper
hollow barn
worn jasper
#

but yeah bitpex explained it

graceful citrus
#

what would be the best way to send objects to another server? i am thinking of just using sockets and object streams but feeling like it might be a bit overkill

graceful citrus
dusty frost
#

Otherwise yeah, serialize and Redis would be your best bet

#

Could go even harder and have a separate http backend and send messages through that

graceful citrus
dusty frost
#

yeah but that doesn't really get you any of the resiliency

graceful citrus
dusty frost
#

well you have to send it through a player's connection, so there has to be at least one online player

minor summit
#

i mean any way you choose is gonna use sockets in the end

#

but going raw and de/serializing data to a byte stream yourself is kinda pepega

graceful citrus
minor summit
#

redis is a cool message broker

#

or how star suggested and make an http service to pipe things through

dusty frost
#

yea redis is awesome

#

gets you lot of resiliency and even if the server is down or something, it will hold the message for em

graceful citrus
#

i guess i could just serialize to json and send through redis

dusty frost
#

yea that would probably be best

graceful citrus
#

when switching servers through bungee order is
preconnect to other server
player connects to other server
disconnects from the current one
right?

#

or is it
preconnect
disconnect
connect

dusty frost
#

second iirc

#

cause you're not allowed to be connected to two at once

graceful citrus
#

i could probably just use the db then no? i need to store the data i want to send anyway so might as well just lock the row on leave and use that as "messaging" effectively

dusty frost
#

i suppose lol

#

are you doing like a player data system or something?

graceful citrus
#

ya synching some data between servers

dusty frost
#

ah yeah you should look at HuskSync

#

It's what I use for my servers, uses Redis for super fast transfer and DB to persist data snapshots

worn jasper
#

I did something like that a while ago with just mysql

#

worked without any issues

#

didn't even require redis

dusty frost
#

yeah most of my fear is related to MPDB and that whole mess

#

so having a lightning fast Redis cache makes me feel a lot better ๐Ÿ˜Œ

worn jasper
#

what could go wrong?

dusty frost
#

latency, database connections, weird locking, etc.

#

with something as critical as player data, having more confidence is always good

worn jasper
#

Eh, latency shouldn't be that big I would say

#

db connections? use a connection pool xd

graceful citrus
#

you kinda need a "hey get this players data" message to be passed to other server

dusty frost
#

idk what specifically went wrong

#

but people lost data and it was not cool

worn jasper
#

if I recall correctly from when I did it, I waited 1-2s before making the request of the data on player join

dusty frost
#

so just half-assing a player data system like that isn't what I would do lol

graceful citrus
dusty frost
#

yeah HuskSync waits like 150ms lol

worn jasper
graceful citrus
#

would rather set up a seperate socket just for "hey data is ready"

#

not really about the player experience

dusty frost
#

2 seconds is defo noticeable too lol

graceful citrus
#

rather solution being bad

worn jasper
#

you have transfer packets now too so, why not use them?

dusty frost
#

what lol

worn jasper
dusty frost
#

that's not really related to this

#

transfer packets are for swapping servers without a proxy

graceful citrus
#

lets say for some reason your db insert / update

#

gets delayed for 2 seconds and player already ends up on the other server

worn jasper
#

but couldn't you transfer data with it?

dusty frost
#

no?

graceful citrus
#

now you pull the old data then

dusty frost
#

not like well

worn jasper
#

I swear I saw that on patch notes

dusty frost
#

and certainly not their entire player data

worn jasper
#

and was even spoken here

dusty frost
#

yeah it's like a few strings

#

and it's user editable

worn jasper
#

I mean, in that case you could do the famous "hey, player data updated"

worn jasper
#

didn't know that

#

but yeah

graceful citrus
worn jasper
#

redis is pog

#

idk tbf

#

I did then like, 4 years ago

#

xd

graceful citrus
#

redis messaging channels is the way to go i guess

worn jasper
#

plugin messaging is also nice personnally

#

but if safety is the issue then redis

graceful citrus
worn jasper
#

in theory the player will already be in the other server?

#

so there will be someone there xd

graceful citrus
worn jasper
#

why is having a player even required?

#

does it send data to a player via the proxy?

#

or what

graceful citrus
#

i got no idea honestly, but it would be so much more useful if it was just a connection between servers

worn jasper
#

yeah, wonder why that's not a thing in more modern proxies

#

like velocity

#

paper and velocity could implement something like this

minor summit
#

the minecraft protocol has a custom payload packet for client <-> server communication, plugin messages is just spigot's name for that

#

being a minecraft packet means that a player needs to exist to use it in its connection

worn jasper
#

oh so it uses that "hack"

minor summit
#

i mean it isn't a hack

worn jasper
#

hence why I put it in ""

minor summit
#

the purpose of the packet is to transmit custom data lol

worn jasper
#

I would call it a mini hack cause it's actually being used in a way that "kinda" isn't meant to be used

minor summit
#

why's that?

worn jasper
#

1s mid valo

graceful citrus
minor summit
#

yes, the purpose is for mods to use that for their communication needs

#

it's also used for stuff like sending the server/client brand

#

debug markers too iirc

dusty frost
#

yeah like Xaero's Mini/World Map use that for sending which map to use

#

which is very useful for servers behind proxies since the client has no way of knowing which server it's on

minor summit
#

chunkyborder uses it because it's cool

dusty frost
#

I think the Logblock Visualizer also uses it which is p cool

hoary scarab
#

Kinda want to make a simple rest api to use between servers. So player isn't required.

dusty frost
#

if only there was this highly optimized program that could act as a message queue between programs ๐Ÿ˜”

hoary scarab
#

๐Ÿคท if only. I prefer my own way though ๐Ÿ˜‰

worn jasper
# minor summit why's that?

I mean, it's intended for client/mods to communicate with the server, and basically what they do is "use" that to communicate between servers.

odd rock
#

can i use javascript by nested?

sterile hinge
#

what

odd rock
#

%javascript_itemattloreline_%javascript_itemattlore_NeutralDamage,1%% this.

#

%javascript_
item_
attloreline_
%javascript_itemattlore_NeutralDamage,1%%

cerulean birch
#

is it at all possible to create virtual worlds/runtime only worlds in bukkit where there's no folder created for them and they don't persist after restarts?

graceful citrus
#

you can "fake" it by creating world and stopping the saves then deleting the files

graceful citrus
cerulean birch
#

ah unfortunate
ty for the response

graceful citrus
#

they change the way worlds are saved, might be able to hijack parts of that process to get rid of io operations by caching

cerulean birch
#

sounds like bukkit doesn't give much of an option to not save worlds
ill take a look at swm though

graceful citrus
#

you cant do it with bukkit, nms on the other hand should be possible

#

if you want to go that route

cerulean birch
#

hm

#

it does make me think though if creating runtime worlds is even efficient

graceful citrus
graceful citrus
#

then it most likely is

#

since the chunks will need to be cached regardless

cerulean birch
#

yeah but it would likely be dozens of relatively small worlds (possible 100+, or around 1 per online)

graceful citrus
#

doesnt matter

cerulean birch
#

hm

#

worlds themselves dont have much overhead/

graceful citrus
#

a player being present = chunks around the player are loaded to memory

#

file is used for persistency

#

when player leaves the area

#

^ you can see how file can be avoided if each "world" would have a player present in your requirements

#

and you dont need persistency

cerulean birch
#

i mean for performance overhead, whether having 30-100 small and near-identical worlds takes up significantly more memory than 1 massive world that has all those small worlds side by side

graceful citrus
#

probably not much

#

you get the overhead of world stats

#

ideally you would group and tick those worlds individually with a custom fork

#

to make it truly scale

#

(similiar to how folia works, but way simpler without the region stuff)

cerulean birch
#

i see

#

my issue with a fork (and kinda nms) is needing to keep maintaining that fork it every time I want to update server version

#

might be a small price to pay for some gains though

graceful citrus
#

if the worlds are the same

#

you can probably just load one world and load from it each time

#

even utilize slime world api

graceful citrus
cerulean birch
#

idea here is for a prison server, each world is a player's mine and only a certain region is modified. rest of the map is loaded either from a schematic or world, whichever way is better

graceful citrus
#

go with folia

#

100%

cerulean birch
#

considering it

graceful citrus
#

single threaded ticking

#

will be your limiting factor

#

not io or memory

cerulean birch
#

i mean

graceful citrus
#

io is only heavy in the sense

cerulean birch
#

most of the action would happen when a player breaks blocks, i dont think much would happen on actual ticks?

graceful citrus
#

you need to wait for the operation, if you put io work on another thread then your cpu is smart enough

#

to do other stuff

cerulean birch
#

ideally i dont want io though

graceful citrus
#

you have to have io

#

at least once

cerulean birch
#

well true

#

thats fine though

graceful citrus
#

you break block = calculation happens next tick when server receives the packet

cerulean birch
#

ah

graceful citrus
#

unless you multithread but thats beside the point

cerulean birch
#

folio does sound like it'd hel pthen

#

i also saw someone here working on a project where one world exists and all players mine there, but everyone sees a unique mining region dependant on blocks they broke themselves/etc)
not sure if thats discontinued/public or not, but i thought it was a good concept

graceful citrus
#

its made for your exact use case

#

divides worlds into regions, so you can tick each "region" individually

cerulean birch
#

hm

graceful citrus
#

with a world where you spread players that much

#

you have the exact use case of folia

tight junco
#

i'm gonna interject and say that its still incredibly experiemental and a large majority of plugins do not work on it due to how it works, your plugin selection will be quite limited

graceful citrus
#

i assumed they are going with a custom plugin setup regardless

cerulean birch
graceful citrus
#

especially if they want to do no io worlds etc

tight junco
#

i expected that too but gotta specify to make sure

cerulean birch
#

๐Ÿ‘

graceful citrus
cerulean birch
#

yeah

graceful citrus
#

would also do j21 so you can use scopes etc

cerulean birch
graceful citrus
#

structured concurrency makes your life easier

cerulean birch
graceful citrus
#

java 21

cerulean birch
#

i got that, i was talking about scopes

graceful citrus
#

adds virtual threads and structured concurrency

cerulean birch
#

oo

graceful citrus
#

effectively coroutines if you used kotlin before

#

or i believe py has it too

cerulean birch
#

sounds like a lot of research needs to be done

graceful citrus
cerulean birch
#

also hypothetically, how would one go about forking paper or its forks like folia? i remember seeing about cloning projects and applying git patches or smthing, havent seen a fully comprehensive guide before though

graceful citrus
#

less memory usage, cpu is the same

#

actually probably not

#

since you need to hold player state yourself then, so about the same

#

you just move who handles the data from server to plugin side

tight junco
#

theres also the paper discord which'll help you a bit more when it comes to help and info about folia wicked

graceful citrus
#

you need a linux instance or you can virtualize it with WSL

graceful citrus
cerulean birch
graceful citrus
#

you dont

#

it just takes quite long to do patches etc

cerulean birch
#

so what does linux instance do for that

graceful citrus
#

package managers

cerulean birch
#

so just apt over homebrew?

graceful citrus
#

if you got a server with docker

#

you can just set it up there as well

cerulean birch
graceful citrus
#

you will thank yourself later for setting it up on anything unix

#

mac works too if you got one

cerulean birch
#

i do

#

interesting
ill take a look into all that, ty

pulsar ferry
#

Pretty sure paperweight works fine on windows now

graceful citrus
pulsar ferry
#

Not really, at least when I tried

graceful citrus
#

then scratch what i said

#

havent used the windows patcher in quite a while

dense galleon
#

Uhh, I got this for loop inside of my saveData method to save player data to my database:

Set<NamespacedKey> namespacedKeys = PLAYER_DATA_REGISTRY.getPluginDataForNamespace(tableName).keySet();
int index = 0;
statement.setString(++index, dataKey.toString());
for (NamespacedKey namespacedKey : namespacedKeys) {
    PluginData<?> playerPluginData = playerData.getPluginData(namespacedKey);
    setValueInStatement(namespacedKey, playerPluginData, statement, ++index);
    statement.addBatch(); // Add to batch instead of executing immediately
}
statement.executeBatch(); // Execute all accumulated commands in the batch```Even though I printed the value of `namespacedKeys` in the console and 3 items are in there, the for loop seems to run only once before exiting. Why could that be?
#

There is no warnings or errors in the console

river solstice
#

any ChatChat users wanna help out?

#

build.gradle:
compileOnly name: 'ChatChat-API-1.0.0-SNAPSHOT'

#

cloned the project, built the API.

#

if I include it from maven, I get an error:

[14:58:32 ERROR]: Could not pass event ChatChatEvent to M0-Pagrindai v1.0.0
java.lang.NoSuchMethodError: 'net.kyori.adventure.text.Component at.helpch.chatchat.api.event.ChatChatEvent.message()'
        at me.m0dii.pagrindai.submodules.chateditor.ChatEditorListener.onChat(ChatEditorListener.java:93) ~[M0-PagrindaiBase-1.0.0.jar:?]
        at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor4712.execute(Unknown Source) ~[?:?]
river solstice
#

or am I using outdated plugin itself, though I downloaded the latest dev build

spiral prairie
#

I just relocated adventure in my plugin because it doesn't have a message API

broken elbow
river solstice
#

also I have a quite a few utility methods that use Components from adventure and they dont work with CC relocated ones

ocean crow
river solstice
#

well, the issue is, if I use the ChatChatEvent and get the event.message(), it returns me the relocated ChatChat component class

ocean crow
#

Lemme setup a workspace for ChatChat, just kinda want to see for myself how it's structured

river solstice
#

and I use adventure from paper itself

dense galleon
#

When loading data from a database synchronously, I take it that if it takes longer than 50ms is when I should worry about performance

#

Since that's when the server may fall in TPS

sterile hinge
#

no, you should worry before (in fact, you should just not do sync database access at all):

  • the latency might differ on the setup (db on the same host? TCP performance of the host?)
  • the latency might scale unexpectedly (it might take far longer with more data suddenly)
  • the main thread might already suffer performance-wise without your database access (if it's already taking up 40ms per tick, a 50ms database access would be bad)
  • depending on what you're doing, there might be multiple requests per tick suddenly
dense galleon
#

Should I be accessing the database asynchronously even on startup/shutdown?

#

I access it asynchronously all the time except those

spring crescent
#

Hey guys, what's the most optimal way of storing inventories or Container contents in MySQL? Here's what I'm currently doing.

if (event.getBlock().getState() instanceof Container) {
    Container container = (Container) event.getBlock().getState();
    Inventory inventory = container.getInventory();

    sqlHandler.insertContainer(container.getBlock().getLocation().getBlockX(),
            container.getBlock().getLocation().getBlockY(),
            container.getBlock().getLocation().getBlockZ(),
            InventoryUtils.inventoryToBase64(inventory)
    );
}

 public static String inventoryToBase64(Inventory inventory) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream);

        // Write the size of the inventory
        dataOutput.writeInt(inventory.getSize());

        // Save all the ItemStacks to the stream
        for (int i = 0; i < inventory.getSize(); i++) {
            dataOutput.writeObject(inventory.getItem(i));
        }

        // For PlayerInventory, save the armor contents as well
        if (inventory instanceof PlayerInventory) {
            for (ItemStack armor : ((PlayerInventory) inventory).getArmorContents()) {
                dataOutput.writeObject(armor);
            }
        }

        // Close the data output and convert the byte array output stream to Base64
        dataOutput.close();
        return Base64.getEncoder().encodeToString(outputStream.toByteArray());
    }
sterile hinge
dense galleon
#

I wouldn't want the plugin to start disabling itself as it's still saving data to the DB right?

sterile hinge
#

yeah

heady maple
#

Getting this error everytime I try to restart server, server randomly crashed @ 60 players
57921 Portal: 34222645
[17:05:35 INFO]: Max TNT Explosions: 100
[17:05:35 INFO]: Tile Max Tick Time: 50ms Entity max Tick Time: 50ms
[17:05:35 INFO]: Preparing start region for dimension minecraft:chunkworld

terse osprey
#

Truly horrifying error

dense galleon
#

How does writing a plugin to handle MOTD in a waterfall/bungee network work?

torpid raft
#

shouldnt be much different from writing a plugin to handle MOTD for a singleton server i imagine

dense drift
#

Is this chat chat integration for a private plugin? If so, you can fork it, replace the spigot api with paper and remove adventure so it uses the one from paper

brittle thunder
#

ChatChat is out?

#

And wasnt it called ChitChat?

broken elbow
#

No and No

torpid raft
#

ChapChat

wet pier
#

what is wrong ?

dense drift
#

Im talking about the plugin where you want to use the chatchat api

river solstice
#

well

#

it's my plugin

#

and it's made with paper

#

this is the issue im facing

dense drift
#

Ok, then you can do what I said, which is to make chatchat use adventure components from paper

river solstice
#

is there a lazy way of doing it

#

cba re-writing CC

dense drift
#

Is not a rewrite, just 2 changes in the build file of chatchat

river solstice
#

not sure what's wrong here lol

dusky harness
#

also, why do you have lines 17-18 when you have paper api ๐Ÿคจ

river solstice
#

don't ask, haven't got around to removing it lol

#

alright I see there's a java version issue

dusky harness
#

ah

river solstice
#

how do you the thingy on build.gradle.kts

dusky harness
river solstice
#

sec

#
java {
    toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}
#

ah it's set somewhere else

#

whatever

#

fixed

dusky harness
#

dont u have to set the target/source compatibility versions

#

oh ok

river solstice
#

yeh fucking around too much

#

should probably have a decent look at the project structure first

plush wigeon
#

Is this where I come to get a hacked account back

river solstice
#

?not-discord

neat pierBOT
#
FAQ Answer:

Looking for discord support?
HelpChat is a Minecraft plugin and development support server and is not affiliated with discord in any way.
If you require support from discord, we recommend you to visit their official support website at https://support.discord.com
On this website, you can read their FAQs, or open a support ticket if necessary.

glossy bane
#

I am having an issue with VaultAPI. My plug in is not able to detect it for some reason. I am compiling with JDK 17 for 1.20.4
My dependency import in the pom.xml is:

        <dependency>
            <groupId>com.github.MilkBowl</groupId>
            <artifactId>VaultAPI</artifactId>
            <version>1.7</version>
            <scope>provided</scope>
        </dependency>

When the function setupChat() runs, it returns false because chatProvider == null

private boolean setupChat() {
        final RegisteredServiceProvider<Chat> chatProvider = getServer().getServicesManager().getRegistration(Chat.class);
        if(chatProvider != null) {
            vaultChat = chatProvider.getProvider();
        }
        return vaultChat != null;
    }

Anyone have an idea why chatProvider.getProvider() is returning null?

glossy bane
dusky harness
#

hmm

#

and you're running setupChat in onEnable?

glossy bane
#

Yep

#
public void onEnable() {
        if(!setupChat()) {
            getLogger().severe("Disabled due to no Vault dependency found!");
            getServer().getPluginManager().disablePlugin(this);
            return;
        }
dusky harness
#

I'm not sure if EssentialsXChat supports Vault

glossy bane
#

I also tried with UltraPermissions

#

Which has its own chat feature as well

dusky harness
#

did you try LuckPerms?

glossy bane
#

No, would prefer to use UltraPerms tbh

dusky harness
#

because UltraPerms isn't listed either, and it's closed source so I can't check the source

glossy bane
#

I should also clarify this plugin has worked before with UltraPerms and EssentialsXChat

dusky harness
#

can you try installing luckperms to see if it returns null or not?

#

and you can remove it after

glossy bane
#

Sure

dusky harness
#

EssentialsXChat doesn't manage prefixes, groups, etc. (why is that even in the Chat vault api?) so it can't support Vault

#

I'd think that UltraPermissions would support it... but I can't check

glossy bane
#

It worked with LuckPerms

dusky harness
#

yeah ig UltraPerms doesn't support it for whatever reason

glossy bane
#

But why doesn't EssentialsChat work?

dusky harness
#

EssentialsXChat doesn't manage prefixes, groups, etc. (why is that even in the Chat vault api?) so it can't support Vault

glossy bane
#

I see, hmm. The plugin I am trying to get to work is a custom global/local chat plugin

#

Something must have changed I guess

#

Cause this use to work with UltraPerms

dusky harness
#

if this is for a private server, you can hook onto UltraPermissions API: https://ultrapermissions.com/wiki/api

Ultra Permissions

Ultra Permissions is the next level Permissions Plugin that can be fully controlled via In-Game Interfaces. It suggests you permissions based on installed plugins, visualises permissions checks and manages your chat all in one interface.

glossy bane
#

Yeah, its a custom plugin for my server

glossy bane
#

Apparently adding UltraPerms as a softdepend fixed it I think

dusky harness
worn jasper
#

how do you use shadowjar in kotlin dsl? (gradle)

dusky harness
#

or if that doesn't work, then tasks.withType<ShadowJar> or something like that

wet pier
#

how can i get these value ?

#

i dont think i can use this

#

@dawn viper

dense drift
#

PlaceholderAPI.booleanTrue()

cerulean birch
#

how do I actually build a paper server jar while trying to make a fork? i cloned the repo, ran the ./gradlew applyPatches, all imports and everything seems to be in order. just not sure which specific tasks or command to run to get a jar and also where that jar will show up (not much of a gradle user)

#

nvm i think i found it. was looking in the wrong file

tight junco
#

also surely its easier to ask this in paper discord

cerulean birch
#

i just assumed that plenty of people here have experience with this and its not a very long explanation of which task/command to run and where it would show up

wet pier
dense drift
#

It is somewhere around these lines, probably on PlaceholderapiPlugin

river solstice
#

suggest giving it a read

cerulean birch
river solstice
#

looking at the wrong place ig

#

createReobfPaperclipJar

graceful citrus
dense galleon
#

Do you guys make your configs in yaml or json?

#

Coming from the modding scene, I feel more comfortable with Json but idk if it really supported

river solstice
#

yml is kinda to-go way

#

since its somewhat "built-in"

dusty frost
#

yaml is just a much nicer human-editable configuration format than json

#

much less syntax to manually write

grand island
#

^

#

toml / hocon is nicer but not that wide used

#

so yaml

digital temple
#

is this possible to let it rain only in certain chunks in one world ?

torpid raft
#

there might be better ways but one way can be by manipulating the biome of each chunk

#

since some biomes don't show rain

digital temple
#

mhh i dont want to change the biom, because the non raining bioms are looking not good. Any other solution for e.g manipulate client packets ?

#

hypixel has this btw too. But i dont know how they do it

graceful citrus
#

just call player.setPlayerWeather

#

on weather change events

#

@digital temple

#

and well check for chunk

terse osprey
#

I donโ€™t think it updates immediately (rain transitions slowly to clear etc). Iโ€™m assuming he wants a more seamless looking route but I donโ€™t think this is do-able for a single dev.

#

And either way stated from bit and Ivan are probably your best bet

graceful citrus
#

in conjunction with listening to this event (completely cancelling it)

#

player wont realize a difference

torpid raft
#

downside to setting player weather is it doesn't make it 'rain in certain chunks' so much as it just makes it rain everywhere or not depending on what chunk you're in

#

i guess it really depends on which one you actually want

dusky harness
#

true, but vanilla minecraft (ex desert biome) doesn't have support for only raining in certain areas iirc

torpid raft
#

yeah all it does is not show the rain animation depending on chunk biome

terse osprey
# graceful citrus player wont realize a difference

Standing on the border of a chunk and looking into the distance seeing rain, only to then walk into that chunk and everything is clear. Youโ€™d be unable to tell from distance if a chunk is rain or clear

#

But it might not matter for the use-case shrug

digital temple
#

another problem with NameSpaceKeys
i will check, if the target itemstack has a specified key from ecoitems.
The current NBT tags shows that the key is this: PublicBukkitValues:{"ecoitems:item":"fishing_rod"}

NamespacedKey key = new NamespacedKey(Main.getInstance, "ecoitems:items");

but NamespaceKeys does only provide [a-z0-9/._-]
Any different solution to get the specified key ?

dusky harness
graceful hedge
#

new NamespacedKey("ecoitems","item")

dusky harness
#

oh

graceful hedge
#

tho its marked as internal on spigot iirc

#

but paper good

digital temple
graceful hedge
#

oh u remove the first arg

digital temple
#
NamespacedKey key = new NamespacedKey("ecoitems", "items");

'NamespacedKey(java.lang.String, java.lang.String)' is marked unstable with @ApiStatus.Internal

graceful hedge
#

yep

#

but ehm, ignore it (hehe)

digital temple
#

sounds not like the best xd

graceful hedge
#

Paper hasnt annotated it Internal, most stuff should run paper (if u dont run paper, u need to reconsider)

#

but ye

digital temple
#

i run paper

#

but i will sell it too

graceful hedge
#

if spigot some how yeets that and make it inaccessible to u, the api consumer, u can flame me

dusky harness
digital temple
dusky harness
#

i forget the exact code
like Bukkit pluginmanager getplugin or smth

graceful hedge
#

correct

digital temple
#
PersistentDataContainer data = itemStack.getItemMeta().getPersistentDataContainer();
NamespacedKey key = new NamespacedKey("ecoitems", "items");

String nskValue = "empty";

if(data.has(key, PersistentDataType.STRING)) {
    nskValue = data.get(key, PersistentDataType.STRING);
}

if(nskValue != null) {
    if(nskValue.equalsIgnoreCase(condition[1])) {
        meetCondition = true;
    }
}

condition[1] = fishing_rod but it fails on nskValue.equals check. Why is ecoitems stressful ._.

terse osprey
#

What is โ€œnskValueโ€ actually set to?

digital temple
#

the name from the item

dusky harness
#

no but like what's the actual value

#

print out nksValue and condition[1]

digital temple
#

its "empty" like defined befor. Because he failed in nskValue.equalsIgnoreCase

digital temple
dusky harness
#

since that's what ecoitems would use itself

digital temple
#

ill think you mean this

EcoItem ecoItem = EcoItems.INSTANCE.getByID(condition[1]);
dusky harness
#

uh

#

no idea what that is

digital temple
#

instead, what you mean ?

dusky harness
#

or EcoItems.INSTANCE ig

digital temple
dusky harness
#

wait no you need EcoItemsPlugin

#

not EcoItems

#

wait

#

if you have the code imported

#

then just use that; there's probably a method for it

#

oh wait

#

im looking in the source (wow, a paid open source plugin!)

dusky harness
#

@digital temple Try ```java
EcoItem ecoItem = ItemUtilsKt.getEcoItem(itemStack);
// do whatever

digital temple
#

lol what is ItemUtilsKt

digital temple
digital temple
#

hell na, kotlin ._.

#

but thanks a lot

#

how do you get this ?

dusky harness
#

ยฏ_(ใƒ„)_/ยฏ

digital temple
#

good for now but currently i think i cant use this
ill get this error on building

java: cannot access com.willfp.libreforge.Holder
  class file for com.willfp.libreforge.Holder not found
digital temple
#

aaaaalright

#

I find the solution finally. You can "test" a CustomStack from ecoItems with another ItemStack
Just use customItem.test(is)

case "ecoitems" -> {
    ItemStack is = Items.lookup("ecoitems:" + condition[1]).getItem();
    if(is != null && is.getItemMeta() != null && itemStack.getItemMeta() != null) {

        CustomItem customItem = Items.getCustomItem(itemStack);

        if(customItem == null) {
            return false;
        }

        if(customItem.test(is)) {
            meetCondition = true;
        }
    }
}
icy sonnet
#

guys I have a question, should I make a String class that just saves all messages so I can just call them as needed in my other classes?

river solstice
#

any ChatChat devs/users can help me figure this out?
I have a custom format for staff-chat with priority (tried with higher AND lower number than default)

for me, it works fine, since, I suppose, I have some permission that changes it, but for my staff, only the channel prefix is applied, the else is inherited from default format

#

for the record, I have given them chatchat.channel.format.staff permission

#

well, nevermind

#

it was chatchat.channel.format.staff.staff

dense galleon
#

Does anyone else struggle with plugins becoming too much of a web with each other? I have a core plugin which I know I want all my plugins to rely on, however there is also two other plugins (One used to add custom items, one as an economy plugin) which many of my other plugins will be depending on which I feel like will make things pretty hectic

#

The thing is that, I depend on that custom item plugin and that economy plugin mainly to just use 1-2 methods from their API I wrote

#

Is there a better way to go about this? It would be neat if my plugins could communicate with each other without depending on one another

worn jasper
#

so you use the api from your eco plugin through the core api

dense galleon
#

Since my currency and item plugins depend on the core plugin

worn jasper
dense galleon
#

How would that forward the other plugin's APIs? I assume it would need to depend on all those other plugins, and then those plugins will need to depend on that "api bridger" plugin which would result in circular dependencies again

merry knoll
#

in your case of 2 3 dependencies it's probably not a big deal enough to use a framework for it

dense galleon
#

(instead of being between classes it is between plugins, in this case)

worn jasper
#

if that makes any sense

#

eco plugin depends on core

#

but not on the bridge

dense galleon
#

Yeah that sounds like it makes sense

river solstice
#

is there a way to parse legacy as well as minimessage formats to component?

#

ex. the text &chello <red>world would be parsed with both legacy and minimsg

grand island
#
package ru.decalium.battlepass.util;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.ComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.jetbrains.annotations.NotNull;


public final class MixedComponentSerializer implements ComponentSerializer<Component, Component, String> {

    private final MiniMessage miniMessage;
    private final LegacyComponentSerializer legacySerializer;

    public MixedComponentSerializer(MiniMessage miniMessage, LegacyComponentSerializer legacySerializer) {

        this.miniMessage = miniMessage;
        this.legacySerializer = legacySerializer;
    }

    @Override
    public @NotNull Component deserialize(@NotNull String input) {
        input = miniMessage.serialize(legacySerializer.deserialize(input)).replace("\\<", "<");
        return miniMessage.deserialize(input);
    }

    @Override
    public @NotNull String serialize(@NotNull Component component) {
        return miniMessage.serialize(component);
    }
}
#

you either replace all legacy color code with their MiniMessage equivalents, or first deserialize it as legacy, then serialize and deserialize again

river solstice
#

eh I just used Kyorifier

#

transform the & shit to <> equivalents and only then parse MM

river solstice
#

the legacy codes got removed but no color applied

grand island
river solstice
#

since Im using ChatChat it already has it

merry knoll
grand island
#

isnt DI was made to invent object oriented programming

dense galleon
dusky harness
river solstice
worn jasper
dense galleon
#

Are firework colors still not editable through paper?

#

When it comes to particles

worn jasper
#

There is also a class named FireworkEffect

merry knoll
dense galleon
#

No I don't mean the fireworks

#

I mean the particle called FIREWORK

dense galleon
merry knoll
river solstice
dense galleon
#

looking it up online most things that pop up are about .net framework or simple dependency injection

merry knoll
#

there are di frameworks for handling load orders and injecting dependencies

dense galleon
#

What is a DI framework though

#

I'm not really following how this applies to plugins or how I'd use that in plugins which depend on one another

lunar tulip
#

im tring to make a apply sytem from google froms to discord but i dont now what im dowing worng here

const POST_URL = "https://discord.com/api/webhooks/##################################";

function onSubmit(e) {
    const response = e.response.getItemResponses();
    let items = [];
https://script.google.com/home
    for (const responseAnswer of response) {
        const question = responseAnswer.getItem().getTitle();
        const answer = responseAnswer.getResponse();
        let parts = []

        try {
            parts = answer.match(/[\s\S]{1,1024}/g) || [];
        } catch (e) {
            parts = answer;
        }

        if (!answer) {
            continue;
        }

        for (const [index, part] of Object.entries(parts)) {
            if (index == 0) {
                items.push({
                    "name": question,
                    "value": part,
                    "inline": false
                });
            } else {
                items.push({
                    "name": question.concat(" (cont.)"),
                    "value": part,
                    "inline": false
                });
            }
        }
    }

    const options = {
        "method": "post",
        "headers": {
            "Content-Type": "application/json",
        },
        "payload": JSON.stringify({
            "content": "โ€Œ",
            "embeds": [{
                "title": "Some nice title here",
                "color": 33023, // This is optional, you can look for decimal colour codes at https://www.webtoolkitonline.com/hexadecimal-decimal-color-converter.html
                "fields": items,
                "footer": {
                    "text": "Some footer here"
                },
                "timestamp": new Date().toISOString()
            }]
        })
    };

    UrlFetchApp.fetch(POST_URL, options);
};```
merry knoll
#

and c depends on b

#

normally you need to manually care about load orders

#

but with a framework you inject these classes

dense galleon
#

Right but how do I make a framework? It feels kinda alien to me to be able to inject classes that are not present in my project

merry knoll
#

you use stuff like singletons and factories

#

look into guice and dagger

dense galleon
#

What about like

#

Having an interface in my core plugin, which for example my economy plugin implements?

#

So that I can use the methods from that economy plugin without actually having it as a dependency?

merry knoll
#

then you lose modularity

#

and unit testability as well (not really used in bukkit development but still )

dense galleon
atomic trail
#

I know this is a very specific question but not sure where else to ask, the essentials discord doesn't really have support for dev questions.

Basically I use EssentialsX Chat to handle chat on a server. I want to add cosmetics to apply a color to player's usernames, ranks etc. and was working on making a ChatRenderer, but this will just override whatever Essentials uses right?

dense drift
#

Is not like eseentials has any complex chat system. It will be better if you replace it entirely

worn jasper
#

ChatChat on top

river solstice
#

well

#

had a few issues with it already

#

an odd bug is that if you are in a different world X in location A, you can see the messages from the world Y in the same location

broken elbow
broken elbow
worn jasper
#
  • open an issue (which already exists)
river solstice
#

we are using it in production environment so it's kinda a dealbreaker rn

#

the issue is probably here

#

it's just comparing distances, but doesn't take world into the account.

worn jasper
#

like variables have different colors, etc.

#

that's quite nice

merry knoll
#

what you probably want is something like gradle bundles im assuming

#

so you dont have to list each dependency every time

broken elbow
graceful citrus
#

monokai pro filter spectrum is amazing as theme

dense drift
broken elbow
#

this + unused/used

worn jasper
#

I use Atom One Dark so

#

Also, yeah now that I think more about it, it can really get messy with changing color variables

broken elbow
#

For you it will probably be named Attom One Dark Copy when you import it. I modified it to give it a better name (in my humble opinion)

worn jasper
#

hell nha

#

bye

dusky harness
#

๐Ÿฅฒ

worn jasper
#

shit font is big af in matt's one

dusky harness
#

font is different than theme ๐Ÿฅฒ

#

thats just blitz's font

worn jasper
#

how do I change font size?

dusky harness
#

i think matt uses fire code tho

dusky harness
worn jasper
#

found it

river solstice
worn jasper
river solstice
#

you might want to turn on the Change font size with Ctrl+Mouse

dusky harness
river solstice
#

yeah

dusky harness
#

fire code

worn jasper
#

ngl like it

#

although I wonder if there is an oled theme

dusky harness
#

i think i use jetbrains mono

#

or fira code idk

#

one of those two

dusky harness
#

๐Ÿ‘€

river solstice
#

i kinda started with C#

#

and found the theme kinda nice

#

that's why I went with it in java too

worn jasper
dusky harness
#

i did not know

#

๐Ÿ˜ฎ

#

game dev?

river solstice
#

also that's not exactly fully the theme, I think rainbow brackets does some coloring for variables too

river solstice
dusky harness
#

ah

river solstice
#

and yes, had quite a fair amount of Unity

dusky harness
#

oh

river solstice
#

๐Ÿฅน

#

in uni we made a shitty tower-defense style game

#

as well as few other ones

#

somewhat a FPS with multiplayer

#

and a VR game

#

based on Iron-lung game

worn jasper
#

Computer Science?

#

or Software Development?

river solstice
#

not sure about the term in english, but probably computer science, yeah

#

had a side study of game dev

#

and probably software dev too

#

but major is compsci, yeah

worn jasper
#

makes sense

broken elbow
river solstice
broken elbow
#

But I also just have scroll to change font size enabled

river solstice
#

Blitz review my issue right now!!

dusky harness
#

Didn't know that was possible from color scheme

river solstice
#

And others too..

broken elbow
river solstice
#

ChatChat

broken elbow
#

It is an issue, alright?

river solstice
#

Fix

#

The

#

Issue

#

๐Ÿ˜ณ

broken elbow
#

Well, that's something compeltely different

#

you asked me to review it

#

I would say 4/5

#

Beautiful issue

#

lacks some details

river solstice
#

Thank you

#

I tried my bestso hard

#

But got so far

#

But in the end

broken elbow
#

Overall, decent. Would recommend to friends and family

river solstice
#

Ir doesnt even matter

#

I might make some PRs, then you WILL have to review them

#

๐Ÿฆ…

broken elbow
#

ok. good

#

I'd rather do that

#

than fix the issues myself ๐Ÿคฃ

river solstice
#

the fix for my issue is like one line of code

broken elbow
#

I am lazy and tired. I have at least 10 issues assigned to me on different projects

broken elbow
#

And testing Spigot stuff is awful

river solstice
#

Though I would like the chat range to be able to work through worlds (shared)

#

Might add that too

broken elbow
#

Do it

river solstice
#

๐Ÿ˜Ž

#

Who else better tests than consumers

broken elbow
#

I don't have a production environment

#

You are my customer

#

So go fix and then go test

river solstice
#

You just.. "fix" the issue, and hope noone creates another ticket

river solstice
#

Works like a charm

#

Being Blitz Id argue your speed in fixing the issues

#

๐Ÿฅธ

broken elbow
#

Dude... I spent like 4 days figuring out why the hell our connection to the DB doesn't work, got multiple AWS tickets created in the process, and the connection still doesn't work sometimes. I am not the right person for the job (whatever the job might be)

river solstice
#

25 open issues on ChatChat, how much you wanna bet I'll make a PR resolving them all tomorrow

#

๐ŸงŒ

brittle thunder
broken elbow
#

I can't be bothered

lyric gyro
#

how would i make something like %identifier_param_<BLOCK>%

lyric gyro
#

i know how to make a normal placeholder

#

but not one with a variable in it

broken elbow
#

I mean, everything after %identifier_ and before the ending % just comes to you as a string

#

so you would get param_<BLOCK> and it would be up to you to parse that

noble hemlock
#

anyone knows the app to overview the maps with schematics?

worn jasper
broken elbow
worn jasper
#

Using AWS is still a big mistake from what I have heard

#

overall relying too much on those services

#

make it hard to transition out of it later on

broken elbow
#

I mean, it is a mistake if you don't have money

#

but if you're a company worth $14B

#

$18B*

#

it probably isn't that bad

#

these web service companies do make it hard to switch off from their platform for already existent apps but, they also make it easy to not have to maintain infrastructure

#

either way, this choice was made years ago, before I even knew what AWS is, or even what a function is.

spring crescent
#

What's the standard for working with MySQL? Should I get data from the DB and update classes whenever the plugin is loaded, then periodically update it at some set interval, or should I only request data whenever I need it and update as needed? It should be noted that I'm working with contents of Container types so it can get big, also I'm using HikariCP for performance gains. Finally, I'm a bit confused, given DB actions are not symmetrical, or async, do I need to be treating them as async with scheduling? In my testing, it seems to be mostly instantaneous, but my DB is also local so idk. Can anyone provide some tips for me? This db thing is kicking my ass.

worn jasper
river solstice
#

mine is only like 3b ๐Ÿ˜”

worn jasper
# spring crescent What's the standard for working with MySQL? Should I get data from the DB and up...

any database requests should be handled async (use the scheduler). Regarding the when to update, etc. it highly depends on the use case:

  • Data is only required every so often: Making a request each time is fine
  • Data is required all the time:
    • Data is from a player: Request on join and cache it. You can then choose to "sync" the
      Database to the cache, aka make updates every x time or not.
    • Data is required for 2+ players or whole server: Request on plugin start and cache it.
#

That's my recommendations. Should note that database requests don't take that long. (unless you do some very unoptimized queries or have a very very large size database)

spring crescent
#

@worn jasper so data is being sent and requested every time someone places a container, or interacts with an inventory. Which could happen with n number of players.

spring crescent
#

Chest, Shulker-Box, Furnace, Barrel, etc..

worn jasper
#

Is that per player?

spring crescent
#

Yes

worn jasper
#

then follow the schema above

#

request on join and cache it

spring crescent
#

And. I'm tracking the contents of said things.

worn jasper
#

Same answer.

spring crescent
#

So no fear of using too much resources?

worn jasper
#

nha, resources are almost never the problem in mc plugins xD

#

when interacting with databases.

#

Just do them async, off the main thread, and you are fine.

spring crescent
#

Lol okay, good to know. I was concerned that 1000+ containers, and their contents, would bloat RAM for minimal gain.

#

tyvm

worn jasper
#

to be a ram issue

#

besides, when players leave, you remove it from cache

#

so, only things actually being used can be used.

spring crescent
#

Unfortunately not. The containers are player agnostic

worn jasper
#

You could in theory even go further down and only load data from loaded chunks

#

but no idea if that's efficient or not

spring crescent
worn jasper
#

can't really check it all rn

#

But why exactly wouldn't you be able to remove from cache on player leave?

#

thought it was player specific only

#

or can other players access those containers too?

spring crescent
#

Basically, the short and sweet is, containers act as a "Seasonal" reward for hardcore servers. Participating players who die, lose their stuff to the survivors. The survivor of x season, can go to a different server, non-hardcore, and claim all of the generated loot, items, etc..

#

Think of it kinda like an Async PubG type gamemode lol

worn jasper
#

was never a pubg guy

spring crescent
#

Fortnite?

worn jasper
worn jasper
spring crescent
#

I'm trying to setup some form of encouragement to give hardcore a shot. People might play it more if there's the potential for rewards if they outlive everyone. xD Eg why chest-data needs to be player-agnostic. Anyone can open a chest at any time and when they do I need to update it's contents such that the DB is always in-sync with what's going on in-game.

worn jasper
#

Just sync every few minutes, that should be fine, as said, you might give the chunk loaded idea a try

#

In theory, should be the most efficient.

spring crescent
#

Yeh so my initial thought was to just cache it all in some data manager, and periodically update. I went away from that for fear of chewing up RAM which has now since been alleviated.

worn jasper
#

You request data on chunk load, when it's unloaded, you put it a "awaiting removal queue" or whatever ya wanna call it, which removes it from cache after a minute or so, this makes it so that if the chunk is loaded again after a few seconds, no need to make a request, you just check if it's in that queue, if yes, get it back to the main cache and voila.

spring crescent
#

I like that

worn jasper
#

that's an idea on how it would be the most efficient I suppose

spring crescent
#

Should be fairly straightforward to implement as well.

worn jasper
#

You can use a caching library like caffeine for caching, it offers time based, size based and whatever caching

river solstice
sterile hinge
#

a true classic

atomic trail
broken elbow
river solstice
#

real

broken elbow
# river solstice real

bcz it shouldn't. the only case this should ever fail if the UUID of a player changes from when they join to when they quit. And the only time I've seen this happen was when people used those cross platform plugins

somber gale
#

Someone here good with maven deploy?
I have a multi-module project with the root only having the pom.xml and no source...
Right now it seems there are issues with the dependency resolving as the modules seem to rely on the parent pom? Is there a way I can make it not needed?

Like I get an error like this if trying to deploy or install: https://paste.helpch.at/uwulinumoq.csharp
Only fix for me is to deploy the parent to local maven repo. Remote is currently skiped as I don't see why I should upload only a pom file for this... But this would obviously cause issues to anyone trying to get the dependency.

stuck canopy
#

Is there a way to change a player's display name which is visible to specific players

#

I am trying to do this using ProtocolLib but I am not sure what Packet to use

dusky harness
stuck canopy
dusky harness
#

uh

#

hold on theres been a convo relating to this recently

stuck canopy
#

wait, theres a Entity called TextDisplay?

dusky harness
#

haven't used them myself since i dont really do mc much but

#

they seem cool

stuck canopy
dusky harness
#

or 1.19 idk

terse osprey
#

TextDisplays are awesome, my favorite part about them is they canโ€™t be seen through walls (on Java) so you canโ€™t see the names of NPCs or holograms through walls

hoary scarab
#

Can do that with entities too. Think its a team object. HideName or something like that.

terse osprey
#

Doesnโ€™t that prevent the name from showing up?

hoary scarab
#

It might. I'm pretty sure there was one that was specific to through walls. Similar to crouching.

terse osprey
#

Erm I donโ€™t think so but maybe, hidename prevents the name all together

terse osprey
#

No idea, but I feel like youโ€™re really trying to shoehorn this โ€œissueโ€ lol

#

There very well might be other ways of doing it, I was just stating the reason I like TextDisplays

hoary scarab
#

Why is it an issue? Just showing its possible with normal entities.

terse osprey
#

Youโ€™re solving a problem nobody is askingโ€ฆ OP (shadow) hasnโ€™t stated that they canโ€™t/wont use the solution somebody provided them. Maybe youโ€™re just posting this alternative method for if somebody were to stumble upon it looking for a non TextDisplay solution?

#

Either way you do you king, if you want to juggle things with armorstands on the NMS side go for it youโ€™re a king. But since textdisplayes were added I was providing my input in response to shadows lack of knowing about them

#

And again Iโ€™ll state if you want to go the entity route go for it, if it works for your usecase amazing. Nothing wrong with it

hoary scarab
terse osprey
#

โ€ฆ ok man ๐Ÿ‘

dense galleon
#

So, I've got this plugin called "Artifacts" which implements custom items for my network.
The current system I have is for any of my other plugins to use a Artifacts#registerArtifact method to register their own items.
This works fine, however if Plugin1 registers an artifact that for one reason or another Plugin2 might need to check for, Plugin2 will need to depend on Plugin1 just for that reason.

#

Which feels quite inefficient?

#

Currently each plugin implementing Artifacts holds static instances of these in a <PluginName>Artifacts class, but again this feels pretty inefficient.

merry knoll
#

why not abstract away the artifact

#

as in pl1 depends on artifacts and uses artifact interface

#

to create and register

#

p2 does not need to know about p1's implementation details

#

it knows Artifact interface

#

etc

dense galleon
#

Yeah I know but

#

If any other plugin needs access to one of these artifact instances

#

That other plugin needs to depend on the plugin implementing that artifact

merry knoll
#

cache them to a name - anything thats global

#

effectively

dense galleon
#

Okay well the current system I have otherwise is, my core plugin has a namespace package where I just store a bunch of public static final namespaces

merry knoll
#

i dont see how p2 would need to know implementation details of p1

#

look at vault for example

#

you know you can access economy through vault

dense galleon
merry knoll
#

ah, are you caching them in a singleton or smt?

dense galleon
merry knoll
#

caching needs to happen on the artifacts plugin

#

not on individual plugins that implement stuff

#

you can ALSO cache there, but access needs to go through the main one

dense galleon
#

Right, but I can't really have public static final variables there

#

The closest thing to that would be a public static final NamespacedKey, Artifact map

merry knoll
#

yes you cant "register" then either

#

regardless

#

have a hashmap

#

with namespace:item as kety

#

key

#

and use that to cache - register - retrieve

worn jasper
merry knoll
#

nah

#

he wants to statically hold the reference

dense galleon
worn jasper
#

-.-

merry knoll
#

but thats not possible since implementation and what is implemented

#

is abstracted away

dense galleon
#

Does it make sense to have a class or multiple classes in my core plugin which holds a lot of singleton NamespacedKey objects?

merry knoll
#

yes

#

thats how di frameworks kinda work

#

in a simple form as well

#

you provide them with a singleton - factory

dense galleon
#

Okay cause that was my 'temporary solution'

merry knoll
#

and they provide instances

dense galleon
#

But then no matter what, I will have to go back to my core plugin and write new namespaces any time I add new instances of artifacts for example

#

I assume that's unavoidable though

merry knoll
#

why not dynamically register them

dense galleon
#

Wdym? Through a register() method?

merry knoll
#

p1 calls register method

#

yes

#

if you need them all in one place make your register method

#

update a file or smt

dense galleon
#

But how does p2 have access to NamespacedKeys registered through p1?

merry knoll
#

it can be plain string

#

or a custom object as key

#

thats provided by the core

#

as in the interface

dense galleon
#

Ah right so i'd just have to "manually" type the string myself

#

Meaning that if for one reason or another, p2, p3 and p4 need to get the same object reference registered by p1 i will have to repeat the RegistryClass.getRegistry().getValue("Something") for each?

merry knoll
#

since these seem to be singletons

#

you can also use the class itself as the key

#

and depend - retrieve from there using it

#

which kinda defeats the purpose but its better than hard coding strings as namespaces

dense galleon
#

Okay so recap

#

My core plugin should have some kind of Registry class that holds Map<NamespacedKey, Object> and a register() method to put items in this map?

merry knoll
#

ideally not object

#

more like some interface

dense galleon
#

yeah a more narrowed down scope

merry knoll
#

ya

dense galleon
#

In my case Artifact

merry knoll
#

and in the case of these all being singletons

#

you can just go

#

LightningArtifact.class as key for example

#

and it gives you its already initialized instance

dense galleon
#

is it fine for it to be an abstract class instead of an interface?

merry knoll
#

i usually do interfaces first then dive into actual implementations*

#

but it does not matter honestly

merry knoll
dense galleon
#

The Artifact class originally was an interface, but I need anything that extends it to have a bunch of code run in the constructor

merry knoll
#

in spigot it doesnt matter honestly

#

you probably want a factory though

#

is my guess

dense galleon
#

An Artifact interface with a Factory subclass? Or what do you mean

#

I don't even know if you can create subclasses in Interfaces tbh, never tried

merry knoll
#

cant comment much without knowing the details

#

but having a lot of shared code usually signals that it can be factorized away

dense galleon
#

Some of the code in there is a year old and I haven't looked at too much

merry knoll
#

ah i see now, abstract class is fine probably

#

unless you run into an issue no point creating one when you dont feel any

dense galleon
#

Okay though I'm thinking

#

if Artifacts depends on my core plugin, I don't really have access to the class ArtifactItem from my core plugin

#

Which means I'd have to move that abstract class to my core plugin right

#

Though is it really correct to have an abstract class in my API package of the core plugin?

merry knoll
#

i would keep it seperate and depend on artifacts

#

on everywhere that uses it

#

if all your plugins will use it you can define it as a transient dependency

dense galleon
#

Not all plugins no, it's just to do so that my map will store Artifact objects as values

#

Instead of just Object

merry knoll
#

why is your map

#

based on the core

#

placed**

dense galleon
#

Ah you recon all the artifacts should be in a map inside of my Artifacts plugin?

merry knoll
#

yes

dense galleon
#

For SRP

merry knoll
#

artifact logic goes into artifact module etc

dense galleon
#

However, my core plugin should have singleton instances of the NamespacedKeys to be placed in the map?

merry knoll
#

if you use keys in other places yes

#

otherwise no

dense galleon
#

Yeah I mean I might

merry knoll
#

i would just modulerize it away personally

dense galleon
#

But in case I want plugin2 to use an item from plugin1, i'd need that key to get the artifact

merry knoll
#

since these are items you can follow mc convention on the namespaces honestly

#

minecraft:grass etc

#

and just go with string

#

i would also probably make a factory on the artifact module

#

to get these items

dense galleon
#

yeah I mean my current namespacekey is plugin:item

dense galleon
merry knoll
#

instead of implicitly calling the "artifacs"

dense galleon
#

I thought factory would be to build the items

#

am I missing something

merry knoll
#

yes to build in your case

#

clone