#velocity-dev

164 messages · Page 4 of 1

reef jacinth
#

You should check isPresent to see if the optional actually has a player.

lilac elbow
#

Alright thanks

#

So like this to check if their online?

wary tiger
#

I suggests multiple improvements: 1.) Make your code object-oriented rather than relying on static access 2.) Name methods according to the casing convention 3.) Don't call the getPlayer method twice. Calling it twice and assuming the value is the same opens you up to a race condition if the Player disconnects asynchronously, although improbable.

rich hawk
#

iirc you can do getPlayer(args[0]).ifPresent(player -> { .... });

slate hamlet
lilac elbow
#

Does .isPresent check if it is an account or if they are online

#

or both

rich hawk
#

If they're online

#

if they're not onlin e it wont be executed

lilac elbow
#

How do you use the config.yml with this

wary tiger
#

You can use any config library of your choice. Velocity includes the Configurate library for simple plugins tou se

magic skiff
#

How i can send players in my own plugin to another server from the spigot side?

#

the same way like in bungeecord?

minor glacier
#

Send a plugin message

#

Or use redis/rabbitmq/message broker

fossil sundial
wary tiger
lilac elbow
#

And velocity already has it built in?

wary tiger
#

"Built-in" in the sense that it's packaged in the jar, yes

lilac elbow
#

Do i need to add it as a dependency

wary tiger
#

No, I don't think

lilac elbow
#

How do I use the Path thing

#

I have the dataDirectory saved, how do I add the config.conf to the path

coarse topaz
#

You'll be better off reading the Configurate wiki, and further questions on that are best suited in the SpongePowered discord

lilac elbow
#

Why is it so hard to use configs in this

low crypt
#

you'll love it when you get used to it

#

i thought the same thing when i wrote my first project using the velocity api

lilac elbow
#

I don't understand this configuration at all

#

How did you learn it

nova sparrow
#

i love velocity!

magic skiff
#

how i can connect player to server on login?

burnt dragon
#

there's a choose initial server event

magic skiff
#

but i have to delete this from config?

burnt dragon
#

uh, well yeah you can use the config too

#

i assumed you were asking from a dev perspective as we are in the dev channel

magic skiff
#

i want to do that players are connecting to a random server

#

in my case lobby

#

because in config they are joining first lobby01, when is full, offline or sth then are joining lobby02

meager sluice
#

You write the logic for that yourself

#

Check which servers aren't full. Get a random number between that amount and boom profit

magic skiff
#

and how i can get RegisteredServer?

lilac elbow
#

Whats the equivalence of ChatColor.translateColorCodes

burnt dragon
#

legacy component serializer

lilac elbow
#

That's the only way?

#

Trying to do it for console logging

burnt dragon
#

well, it's your code you can program whatever way is possible

#

but velocity uses components, so the legacy component serializer is the best method for turning legacy formatting into components

magic skiff
#

how i can set this?

burnt dragon
#

there's plenty of methods on ProxyServer that allow you to get/create registered servers

vestal prawn
#

ProxyServer#getServer i can't remember the name correctly but it's something like that

#

and you give the server name

night saddle
#

At which point during a player being transferred from server A to server B is the connection to server A severed?

#

Found it, TransitionSessionHandler

fossil sundial
#

Till then the new connection can be aborted

night saddle
#

Not event-wise, doing custom fork things

fossil sundial
#

Well alright, as long as you follow the license feel free to ask more technical questions

#

@night saddle are you making a custom backend <> proxy forwarding system /w encryption?

night saddle
#

I'm not sure what you're asking

fossil sundial
# night saddle I'm not sure what you're asking

Someone told me you’re tinkering around with a custom data exchange and encryption between server and proxy
Whatever the case may be you may be interested in tinkering around with the login plugin message api in velocity
Also since you touched the transition handler; fair warning, if you intercept packets or disconnect the old server quicker you may have to send a fake Respawn/join game combination to keep the client from getting stuck

#

I lost track of how much time it took me to debug that mess

night saddle
#

That was my old solution to the problem

#

My solution now is to use redisson locks & such

sacred musk
#

Hello, I have

#

    @Subscribe
    public void onPluginMessage(PluginMessageEvent e) {
        System.out.println(e.getSource());
    }

}```
#

And it does not work

#

As I read from the docs, it should be fired when a plugin sends message to the player, am I wrong?

#

Never mind, I am wrong, another question, is there any event related to the messages send from proxy to the player?

lilac elbow
#

I have a .toml file in my resources, but it isn't being loaded, is there something I have to do to load it? If I create it and put content in it I can load the file, but it's not creating one just by being in the resource folder

sacred musk
lilac elbow
half locust
#

?

lilac elbow
#

args.length is giving me it

#

This is in a execute function of a command

rich hawk
#

check if null first?

lilac elbow
#

Tried that same thing

rich hawk
#

whats the error now

lilac elbow
#

Same error

rich hawk
#

do a clean build

lilac elbow
#

Why would that make a difference?

rich hawk
#

to make sure you're actually running the new jar cus the error shouldn't be the same with that afaik

lilac elbow
#

Clean build same error

atomic leafBOT
#

Please send large files/logs to a pastebin

lilac elbow
#

I'm printing the Exception response message

#

Not much to show that screenshot is the entire thing

wary tiger
#

You're not showing the location where you call String.length()

wary tiger
# lilac elbow

As the message states, length() is a method you tried to call on a null String

lilac elbow
wary tiger
#

This is different from accessing the length field of an array

#

config.getString is returning null, most likely

lilac elbow
#

Let me see

wary tiger
#

Add Objects.requireNonNull to your Common.sendMessage method. That'll make matters absolutely clear

lilac elbow
#

Its not the config.getString

#

Removed it completely same error

wary tiger
#

Show Common.sendMessage

lilac elbow
#

Don't think it's this either working for everything else

wary tiger
#

Add Objects.requireNonNull(message, "message") to this method

#

Add that at the beginning of the method

lilac elbow
#

I don't know how to use that

#

source.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(message));

wary tiger
#

I.e.:

public static void sendMessage(CommandSource source, String message) {
  Objects.requireNonNull(message, "message");
  source.sendMessage(...);
}
#

Then run your code and this will allow you to determine whether message is null

lilac elbow
#

Alright

#

Hm

#

It gave me an error message of just "message"

wary tiger
#

Right

lilac elbow
#

message not error

wary tiger
#

message is null

#

NullPointerException: message -- that's what you saw, isn't it?

lilac elbow
#

No I'm only logging the exception message

#

Ignore color codes

wary tiger
#

Don't catch and log exceptions. Simply let them be thrown

lilac elbow
#

Caused by: java.lang.NullPointerException: message

wary tiger
#

Exceptions are your friends; they tell you what went wrong in your code, where, and often why. If you hide exceptions, you'll spend more time debugging and more time annoyed at your code because it doesn't work. If you let the exceptions show themselves, you'll find out the cause of the bug much more quickly and your software will become more robust overall.

#

Congratulations, now you know how to use Objects.requireNonNull to fail-fast in your code

#

Indeed, config.getString is returning null

lilac elbow
#

Why can't papermc make a simple config system

#

I spent all name writing a toml handler

#

and now i must fix it

coarse topaz
#

It isn't an issue of papermc

lilac elbow
#

I know

coarse topaz
#

just learn to use configurate

lilac elbow
#

Never

wary tiger
#

If you don't want to use configurate, there are other configuration libraries you can choose from

lilac elbow
#

Yeah I'm using toml

wary tiger
#

I don't use Configurate either

lilac elbow
#

See configurate sucks

coarse topaz
#

It doesn't you just don't know how to use it

lilac elbow
#

You guys don't even have a tutorial on it because even you guys can't figure it out

wary tiger
#

I don't think that's true

coarse topaz
#

Did you look at the wiki?

lilac elbow
#

The velocity one yes

coarse topaz
#

they even have written code examples for more involved issues

wary tiger
coarse topaz
lilac elbow
#

I love how you always recommend your own stuff

#

You made something for every scenario

wary tiger
#

I'm not the only one who uses it: you can look at who else does

coarse topaz
#

a248 does make some nice libs

lilac elbow
#

Do you just shade dazzleconf?

wary tiger
#

Thanks for the compliment, Allen

wary tiger
# lilac elbow Do you just shade dazzleconf?

Yes, you would, like any other library. Though I should mention this isn't the place to seek support for DazzleConf (whereas Configurate is suggested by the Velocity API so it makes sense to ask here)

lilac elbow
#

They tell me not to ask about configurate here

#

Probably because they can't understand it either

wary tiger
#

Oh right, you should ask in the SpongePowered discord

#

They have a dedicated channel for Configurate there

valid gazelle
#

how do i make the tab completion with BrigadierCommand match things that start with the current text you typed for the argument, instead of everything? i don't like how it shows everything no matter what text i typed because if i try and tab it in, it replaces it with something comopletely random

fossil sundial
valid gazelle
#

i think that's what i'm using right now, here ill try and get an example snippet from one of my commands

coarse topaz
#

I did something like this

#

the way you are doing it is just adding suggestions, not filtering them

valid gazelle
#

hmm ill try that

valid gazelle
coarse topaz
#

Uh, I am not sure. I wrote all of this almost a year ago so I am not sure if something has changed

valid gazelle
#

hm i wonder why it works in yours then

#

i guess ill just split it and get the last string after a space

craggy pecan
# valid gazelle i guess ill just split it and get the last string after a space
GitHub

Brigadier is a command parser & dispatcher, designed and developed for Minecraft: Java Edition. - brigadier/CommandContext.java at cf754c4ef654160dca946889c11941634c5db3d5 · Mojang/brigadier

craggy pecan
#

Forget everything I said above, use SuggestionsBuilder#getRemaining()

#

Iirc that string should only contain the argument for which suggestions are being computed

lilac elbow
#

if I do /command it gives me the correct options for args0 and args1 if I don't type anything in, If I type anything in args0 for example /command g
it will show the options for args1

valid gazelle
#

It worked

frosty star
#

is there something like PlayerChatEvent for player deaths / advancement type messages?

jolly atlas
#

smth like that

frosty star
#

i assume you mean in the handler for PlayerChatEvent, that event isnt triggered for deaths or advancements

vestal prawn
#

What is the default configuration file system implemented in velocity ?

#

Toml ? Yaml ? Both works

#

Will there be a deprecated one in the future ?

#

Or a preferred one ?

ashen fiber
#

There is no default

#

It is recommended to use sponge's configurate.

#

Personally I just use kotlin's JSON but I will probably switch to configurate.

#

@vestal prawn

vestal prawn
#

Thanks didn't know about it

#

i used toml, I'll switch if configurate is easier

ashen fiber
#

Never used either so

#

¯\_(ツ)_/¯

#

As I said, I'm just using kotlin's json

#

Because it loads into a fancy config data class which is easy to read from.

craggy pecan
#

The code should do /command->fileSuggestions, /command something->suggestions, /command foo b->stream, /command a b c->(empty list)

#

Unless there's a trailing whitespace, in which case Velocity will add an extra empty string to the args array

lilac elbow
#

I do /command then its suppose to suggest test1 or test2 which it does if i type in no letters and just hit space after /command. Then if i do /command test1 it will give me options for test3 or test4. So /command test1 test3. But if I do /command and type t so it looks like /command t it will suggest test2 and test3

craggy pecan
#

In /command test1 is there a trailing whitespace char?

#

I can't understand what test1, etc refer to since I don't know the actual variables. Can you share those instead?

lilac elbow
#

Test1 = config.yml test2 = messages.yml test3 = get test4 = set

#

So if i start typing /command config.y it will suggest get and set

#

But if i dont type anything after /command it suggests config.yml and messages.yml

hearty beacon
#

hello! i'm working on porting a plugin from bungee to velocity, most of it's been fine, but i'm having an issue with a LoginEvent listener, what i'm trying to do is cancel the event if the player is banned using event.setResult(ResultedEvent.ComponentResult.denied(VelocityServer.formatMessage(message.toString()))); that doesn't seem to do anything though, i still connect normally while banned and it doesn't stop me from joining

craggy pecan
lilac elbow
#

Ah alright

wary tiger
#

I use the exact same method in LibertyBans (another ban plugin)

hearty beacon
#

the listeners method? should be called in the main class

wary tiger
#

Add a debug statement or use a debugger to confirm

hearty beacon
#

that would be a good idea, will check that

#

and yep, the event is not getting fired

#

hmm, why isn't it though, the listener should be registered and everything seems to be right?

lilac elbow
#

I have these files in the resources, why when I try to get them they don't exist?

vestal prawn
#

you need to use something like this : ClassLoader#getResourceAsStream(<path>), to first copy your file and then read it

lilac elbow
#

Where should I call it?

#

on Initialize or where I need it

vestal prawn
#

in the constructor of your plugin i believe, i never did that but i know it's how we do it

#

i think you need to first get your file with the method above, and then you can copy it to your plugin folder (if the config file was not here) and then read the config file

lilac elbow
#

Still doesn't work

wary tiger
#

You can access those resources at any time

lilac elbow
#

How?

wary tiger
#

getResourceAsStream returns an InputStream

#

an InputStream is merely a stream of data. If you want to write it to a file, you have to do that

#

you should always use try-with-resources when working with InputStreams

lilac elbow
#

I just need the file to load

#

And be created

wary tiger
#

Yes, so do what I suggested

lilac elbow
#

with the same content that is in it in the editor

#

Alright

wary tiger
#

You can use Files.copy(stream, destination) to copy an input stream to a file path

lilac elbow
#
    private void LoadFile(String path) {
        File filePath = new File(getDataFolder().toFile(), path);
        try (InputStream input = Tailop.class.getResourceAsStream("/" + filePath.getName())) {
            if (input != null) {
                Files.copy(input, filePath.toPath());
            } else {
                filePath.createNewFile();
            }
        } catch (IOException exception) {
            Common.log(getClass().getName() + " [TAILOP] [ERROR] " + exception.getLocalizedMessage());
        }
    }
#

Look right?

wary tiger
#

Use proper casing conventions

#

Don't perform unnecessary null checks

lilac elbow
#

input always equals null

wary tiger
#

Rethrow exceptions rather than swallowing them - throw new UncheckedIOException(exception)

wary tiger
lilac elbow
#

Could it be the "/"

wary tiger
#

The resource should be something like "/config.yml"

#

The / is right

lilac elbow
#

The thing is though

wary tiger
#

I've seen that before

lilac elbow
#

I even created the file

#

and restarted the server

#

and it still can't find it?

wary tiger
#

What is filePath.getName() returning? Find out

#

Also, I don't know why you're converting to and from java.io.File when you could much more easily use Path.

lilac elbow
#

I'm more familiar with C#

wary tiger
#

getDataFolder() returns a Path and Files.copy uses a Path so using a Path will avoid the need to use toFile() and toPath()

lilac elbow
#

More similiar to it

wary tiger
#

This is Java, not C#

lilac elbow
#

I know

#

filePath.getName() returns work.yml

wary tiger
#

Are you sure it exists inside the jar, then?

lilac elbow
#

How would I check

wary tiger
#

Unzip it

#

unzip works on jars

lilac elbow
#

Yes its in it

#

Could it be the filepath?

#

Its trying to load it from ./Server/plugins/tailop/work.yml

hearty beacon
wary tiger
#

If filePath.getName() returns work.yml then it will work as expected

lilac elbow
#

But its not copying the data

#

Its creating the file

wary tiger
lilac elbow
#

Not copying whats inside

hearty beacon
#

huh

wary tiger
lilac elbow
#
private void LoadFile(String path) {
        File filePath = new File(getDataFolder().toFile(), path);
        try (InputStream input = Tailop.class.getResourceAsStream(File.separator + filePath.getName())) {
            if (input != null) {
                Common.log("CALLED");
                Files.copy(input, filePath.toPath());
            } else {
                Common.log("NEW FILE " + filePath.getName());
                filePath.createNewFile();
            }
        } catch (IOException exception) {
            Common.log(getClass().getName() + " [TAILOP] [ERROR] " + exception.getLocalizedMessage());
        }
    }
wary tiger
#

Don't use File.separator

lilac elbow
#

Bruh

#

I asked and you said yes

wary tiger
#

Yes, / is right, and the resource should be something like /config.toml

#

Those are both true statements

#

However, the resource path should not be ./Server/plugins or any such expanded path

lilac elbow
#

File filePath = new File(getDataFolder().toFile(), path);

#

path = file name

#

so it should be:
File filePath = new File(path);

wary tiger
#

Use path instead of filePath.getName()

wary tiger
#

I really do suggest you use Path instead of File; there's really no reason to use File for new code

lilac elbow
#

How do you create a path

wary tiger
#

getDataFolder().resolve(path) gives you the file you're looking for

lilac elbow
#

How would I add the file onto it

#

oh nvm

#

Alright using path, now what

#
 private void LoadFile(String path) {
        Path filePath = getDataFolder().resolve(path);
        try (InputStream input = Tailop.class.getResourceAsStream("/" + filePath)) {
            if (input != null) {
                Common.log("CALLED");
                Files.copy(input, filePath);
            } else {
                Common.log("NEW FILE " + filePath);
                new File(String.valueOf(filePath)).createNewFile();
            }
        } catch (IOException exception) {
            Common.log(getClass().getName() + " [TAILOP] [ERROR] " + exception.getLocalizedMessage());
        }
    }
wary tiger
#

getResourceAsStream("/config.toml") will do what you want

#

Instead of "/" + filePath (which will include the data folder), you need to use "/" + path

lilac elbow
#

You are so confusing

#

I asked that earlier too

#

And you also said no

wary tiger
#

The jar doesn't know anything about the data folder; getResourceAsStream fetches a resource from the jar

wary tiger
wary tiger
lilac elbow
#

It returns work.yml

#

Ok it's working now

#

For the suggest command, /command arg1, arg2, arg3 what would be the right args[number] for arg3

wary tiger
#

I believe 2

#

I've grappled with tab completion many times over, so I'm not the best at it

#

If the argument after arg3 is tab-completed, I believe the last element in the argument array will be an empty string

wary tiger
hearty beacon
#

still the same issue, but that might be why its happening

#

no idea whats causing it though

wary tiger
#

Are you sure the line registering the listener is called?

hearty beacon
#

yep

wary tiger
#

Are you sure the initial line where you receive the event is called?

hearty beacon
#

yes, it is definitely being called

#

ah, that just showed up, that would be why

#

yep and now it works, i was just blind lol

magic skiff
#

how to check if initialserver is online?

bold wharf
#

is there a ping method?

#

cos, basically, pinging it or just trying to connect and dealing with it failing is the only real way to check if something is accepting connections

lilac elbow
#

nope no ping

#

Sorry bad joke just worked perfectly

lilac elbow
#

Does Snakeyaml have a support discord

rich hawk
#

Google

valid gazelle
#

Is there a better way to get UUIDs of offline players other than querying the mojang api and then caching it in my plugin directory? I know on bukkit/spigot there's Server#getOfflinePlayer(String), but is there an equivalent for velocity?

rich hawk
#

No

vestal prawn
#

No

#

If you use luckperms you can use their cache

#

Or cache the username until the player connects you get their uuid

lilac elbow
#

Getting this in console:

[13:56:52 INFO] [tailop]: [motd=&e&lThe best server
&aJoin us now!, hide_player_count=false, max_players=+1000]
[13:56:52 ERROR]: Couldn't pass ProxyPingEvent to tailop
java.lang.NullPointerException: Cannot invoke "java.util.Map.entrySet()" because "data" is null
        at org.tailop.util.config.YamlConfiguration.getString(YamlConfiguration.java:80) ~[?:?]
        at org.tailop.events.ServerHandler.onServerPing(ServerHandler.java:53) ~[?:?]
        at org.tailop.events.Lmbda$7.execute(Unknown Source) ~[?:?]
        at com.velocitypowered.proxy.event.UntargetedEventHandler$VoidHandler.lambda$buildHandler$0(UntargetedEventHandler.java:47) ~[Velocity.jar:3.1.2-SNAPSHOT (git-b8f1df44-b110)]
        at com.velocitypowered.proxy.event.VelocityEventManager.fire(VelocityEventManager.java:598) ~[Velocity.jar:3.1.2-SNAPSHOT (git-b8f1df44-b110)]
        at com.velocitypowered.proxy.event.VelocityEventManager.lambda$fire$5(VelocityEventManager.java:479) ~[Velocity.jar:3.1.2-SNAPSHOT (git-b8f1df44-b110)]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?]
        at java.lang.Thread.run(Thread.java:833) [?:?]

this is the code

78 public String getString(String path) {
79         Map<String, Object> data = this.yaml.load(this.inputStream);
80        Common.log(data.entrySet().toString());
81        return String.valueOf(data.getOrDefault(path, null));
83    }
rich hawk
#

do more debugging

lilac elbow
#

What?

rich hawk
#

inputstream, yaml etc

lilac elbow
#

Thats not the issue

#

Its getting it into the map so I know its loading

rich hawk
#

Well something is null

lilac elbow
#

It's being called in a ProxyPingEvent

#

When its called through anything else it works fine it's weird

#

And I checked how its being called over and over nothing is wrong with it

grizzled rapids
#

How to suggest player a tab completion with two different completion lists like
/rank {player1, player233, player404} {player, staff, admin}

valid gazelle
vestal prawn
#

I can't remember exactly

#

and then User#getName

#

something like this

wary tiger
lilac elbow
#

Ah alright

lilac elbow
#

@wary tiger are you familiar with snakeyml at all? I'm trying to make it so if you put a . in the key for example t1.t2 and value of test
it would look like
t1:
t2: test

wary tiger
#

Yes, I'm familiar with it. I've used the snakeyaml Node API before

lilac elbow
#

Do you know how to do what I'm trying to ask

#

And if so could you show me how

wary tiger
#

Oh I see, yes

#

I think you want to interpret dotted key paths and fetch the corresponding config value, right?

lilac elbow
#

Yea

wary tiger
#

A configuration is really a Map of Maps

lilac elbow
#

Thats what I figured I would have to do

#

Was just wondering if there was a built in way

wary tiger
#

The top-level configuration is a Map<String, Object> -- you can cast to that and then retrieve values as needed

#

Not in snakeyaml. you need to write code to expand the dotted key, then recursively fetch the value

#

(you don't necessarily need to use recursion but it's probably easy to do it that way)

lilac elbow
#

So pretty much Map<String, Map<String, Object>>

wary tiger
#

yes, that's about right

#

Keep in mind: normal config options (which aren't further configuration sections) won't be Maps

lilac elbow
#

I don't need them

wary tiger
#

Imagine:

Map.of("integer-value", 1, "section", Map.of())
#

A Map of Maps, but the values can be either Maps or configuration values

lilac elbow
#

How does spigot do it?

#

Don't they use snakeyaml?

wary tiger
#

The Bukkit config library uses snakeyaml, but it also uses a lot of bad practices which I don't recommend, such as swallowing exceptions

lilac elbow
#

Is it open source?

rich hawk
#

yes

lilac elbow
#

Where can I find it? Its not on their github

rich hawk
#

you need to compile Bukkit

#

Or paper

wary tiger
#

you can use your IDE to view the sources for the paper API

#

In terms of the broader objective, I wonder why you do not use a simple configuration library which handles these semantics for you

half locust
#

configurate ❤️

lilac elbow
#

Never

fossil sundial
#

I mean I’ve seen people shade the bungee-config module

#

It’s entirely possible but I advise against it

lilac elbow
#

Do you advise against it because you are a paper dev or an actual reason

fossil sundial
#

I advise against it because there are some things it requires which aren’t in that module. It may work fine but it may also just blow up

wary tiger
#

an other actual reason is that bungee-config is a poorly designed configuration library, similar to bukkit's

lilac elbow
#

What if you shade the entire bungee module

#

Easy solution

rich hawk
#

Just don’t

fossil sundial
#

Good luck relocating everything or you’ll get overlapping

#

Also Lombok processing will take a literal year

lilac elbow
#

I have a request for you

#

Remove configurate

#

Make a snakeyaml system

#

ty

rich hawk
#

No

half locust
#

why...

fossil sundial
lilac elbow
#

What features does configurate have that makes it superior to snakeyaml

rich hawk
#

Not being just yml

lilac elbow
#

??

rich hawk
#

(Amongst others)

half locust
#

object mapping, config generation, hocon support, proper comment support...

lilac elbow
#

Config generation?

half locust
#

I think it also has a basic versioning system for changing the config

fossil sundial
#

It does. Configurate is just a framework system that has quite a few supported config adapters
Gson, hocon, yaml and a few more

#

There is also a way to constrain values intelligently that I’ve never touched

lilac elbow
#

What's config generation?

half locust
#

i.e. I have a class (I use kotlin, but same works for java) @ConfigSerializable data class ConfigExample(var option1: Int = 69, var otherOption = "hehe", var other: SomeClassWith@ConfigSerializable? = null). I call a few methods, and it spits that out as a config

lilac elbow
#

Just creating the file? Or does it generate parameters

#

Ah

#

I mean

#

thats pretty simple to do though

#

snakeyaml you can do that

#

sorta

#

Actually yeah if you have to call a few methods then snakeyaml does the same thing

wary tiger
#

A good configuration library will do that for you; the difference is how

half locust
wary tiger
#

Do data classes generate setters?

half locust
#

in that case it's all immutable, but mutable configs are ok too

#

(val (immutable) vs var (mutable))

#

this is kotlin

vestal prawn
#

is that java 17

#

oh kotlin

fossil sundial
#

Might as well be java 17 with record classes

half locust
#

but muh extension and operator functions

lilac elbow
#

How do you get an offline player by their uuid

fossil sundial
#

You don’t. If you need data then you either need to cache it or pull it from the mojang api

lilac elbow
#

How do you do that

#

mojang api

#

Do I need to shade it

fossil sundial
wary tiger
#

It's a different kind of API

lilac elbow
#

Only done http requests in javascript

#

time to learn

fossil sundial
#
 public static CompletableFuture<User[]> queryMojangApi(AsyncHttpClient client, String[] username) {
        Preconditions.checkNotNull(username, "username");
        Preconditions.checkNotNull(client, "HttpClient");
        Preconditions.checkArgument(username.length > 0, "no username");
        Preconditions.checkArgument(username.length <= 10, "too many usernames");

        CompletableFuture<User[]> ret = new CompletableFuture<User[]>();
        String dataPost = GSON.toJson(username, String[].class);
        client.preparePost(PROFILE_ENDPOINT_MULTI_POST).setBody(dataPost).execute()
                .toCompletableFuture().thenAcceptAsync(result -> {
                    if(result.getStatusCode() == 200) {
                        try {
                            JsonObject[] profiles = GSON.fromJson(
                                    result.getResponseBody(StandardCharsets.UTF_8), JsonObject[].class);
                            User[] data = new User[username.length];
                            for(JsonObject profile : profiles) {
                                User contained = fromJsonObject(profile);
                                for (int i = 0; i < username.length; i++) {
                                    if (username[i].equalsIgnoreCase(contained.getName())) {
                                        data[i] = contained;
                                        break;
                                    }
                                }
                            }
                            ret.complete(data);
                        } catch (Exception e) {
                            ret.completeExceptionally(new IllegalStateException("Invalid API response", e));
                        }
                    } else {
                        ret.completeExceptionally(new IllegalStateException(
                                "API returned status code " + result.getStatusCode()));
                    }

                }).exceptionally(throwable -> {
                    ret.completeExceptionally(new RuntimeException("Bad request", throwable));
                    return null;
                });

        return ret;
    }
#

That’s roughly how I did username > UUID

#

The user class is just a record class with the properties the api provides

lilac elbow
#

nvm

fossil sundial
#

This is just an example. Do ask if you have questions. That snippet can be treated as under the unlicense license

latent kelp
#

Hey, how do I make it so switching between servers it doesn't unload then load the texture pack? If one of the servers is 1.12 on the network and I join it from a 1.17 server, it keeps the texture pack and no unload screen or load screen shows even tho that server doesn't have the texture pack in the settings, but if I join the 1.17 server from the 1.12 server it unloads the texture pack and loads it again

#

If I then go from 1.12 to a 1.12 I also get no loading screen either, even tho I'm on the same mc version

fossil sundial
latent kelp
#

Actually after more testing, it seems the loading screen and unloading screen only happens when I return back to the server the texture pack is set on

#

I just went from a 1.17 -> 1.12 -> 1.12 -> 1.18 -> 1.17 (a different one to the original) then back to the original and it only did a loading screen when going to the one its hosting on

fossil sundial
#

Oh, that.

latent kelp
#

but I had the texture pack on all the others

#

I've been trying to get this behavior for months and I've randomly come across it, but I'd prefer if there wasn't an unloading and reloading when going back to the original

lilac elbow
#

Does via version work in velocity?

fossil sundial
fossil sundial
latent kelp
#

The hash is provided

lilac elbow
#

What does it mean see yourself blocking?

fossil sundial
fossil sundial
latent kelp
lilac elbow
#

I know but does it mean like sword blocking?

fossil sundial
#

Yes. Ladders and lilypads and potions are the same deal

#

They just don’t work correctly

lilac elbow
#

So its better to just add to each individual server?

fossil sundial
latent kelp
#

I actually want it to work like this though just not reset it when joining the original server which set the resource pack, is there a way to do that?

fossil sundial
#

No, I know why this happens. The resource pack queue velocity has causes it, but to fix it I have to change a few things that might break older clients

latent kelp
#

Can you point me to where in velocity handles this?

fossil sundial
latent kelp
#

thanks

fossil sundial
# latent kelp thanks

There is a bug in that logic already that should be fixed in the PR by @oblique haven
I just don’t have time for all of this till mid February

oblique haven
#

wave

#

my PR fixes it, but my PR isn't done

#

still have to add one more line of code

latent kelp
fossil sundial
#

That’s not the issue I was referring to

#

But it’s fine

#

PRs to this are welcome

oblique haven
#

you're talking about the Origin issue right

fossil sundial
#

Yea

latent kelp
#

Whats that?

fossil sundial
#

The proxy is incorrectly swallowing responses

#

Oh actually

#

That might be the issue you have

#

Why didn’t I think of that before

#

I see how it could be

#

Okay, yea, no that’s not the issue

#

@latent kelp the re-loading screen happens because the server re-sends the apply-resource-pack request each time you join

#

but you only want to send it once when the player first joins right?

#

hash doesn’t matter on newer versions, it only does for downloads. It will respond by re-applying it anyway

latent kelp
#

Correct, I don't want it to resend once a player first joins unless they join a different server in the network which has a different resource pack, but from my debugging I can check if previousResourceResponse is true and then if it is just don't send the resource pack to outstanding, I could then add a check to see if its different from the origin

fossil sundial
#

that’s what I’d do on velocity to “fix” it

lilac elbow
#

Can you use a velocity api in a paper plugin?

fossil sundial
lilac elbow
#

like i have my core as a velocity plugin, but need to access it from plugins running off paper

#

Core is on velocity server

#

need to access it from paper servers

fossil sundial
#

Do you only need to access features of it when a player is connected?

lilac elbow
#

Yes

#

The core is storing all player data

#

Just need to call it and get the player data when they do stuff

fossil sundial
#

In that case you could create your own plugin messaging channel communication

lilac elbow
#

Is it the same for velocity as bungee

wary tiger
#

Since the proxy and backend server are different processes, you can't call methods directly in one from another

fossil sundial
lilac elbow
#

I might just make a server to handle it

#

Because it's just storing player data

#

But needs to be global

latent kelp
fossil sundial
#

ACCEPT, DOWNLOAD, SUCCESS

#

I might be mistaken here but I think DOWNLOAD is still sent even if the hash matches

#

@oblique haven you know this by chance?

#

otherwise its going on my to-do-list

latent kelp
#

Yeah this is the perfect behavior I wanted, I'd assume you guys are going to put a patch in to fix it so it resets each time tho, I'll just have to fork it and make sure those changes don't go live

fossil sundial
latent kelp
#

Yeah that would be good, currently the other servers don't have the texture pack set to anything, I guess my fix for now could see if the texture pack which its trying to queue hash matches the previous one and then just swallow it so it doesn't load it, but if that could be added, that would be great 🙂

fossil sundial
#

I should also maybe add API to force-clear resource packs

fossil sundial
lilac elbow
#

To check if a server exists would I do if(Main.getServer().getServer(args[1]) != null)

fossil sundial
#

don’t use .getServer(name) twice. Do it once and store the result. In the time that happens it might no longer be present

lilac elbow
#

I know that was just an example

fossil sundial
frosty star
#

is there any way i could get those messages? maybe a plugin on the servers?

fossil sundial
#

Yes that would work
You’d be ideally be using a custom plugin channel to get that from server to proxy

frosty star
#

are there any examples on how to do that from paper > velocity and/or fabric > velocity

craggy pecan
#

For Paper > Velocity, you can check the Spigot wiki on the BungeeCord messaging API (replace the BungeeCord channel by your own)

#

Or if you prefer it, check the javadoc on Player#sendPluginMessage iirc

olive quartz
#
        Audience.audience(
                EssentialsPlugin.getProxyServer().getConsoleCommandSource(),
                EssentialsPlugin.getProxyServer()
        ).sendMessage(component);

Why can only players see the message sent like this, but the console will not display it?

#

I'm pretty sure that when I use EssentialsPlugin.getProxyServer().getConsoleCommandSource().sendMessage(component); alone, the console can display

#

Is this a bug? Or is the design so?

fervent mantle
#

Is there a way to dispatch a command from console?

#

Found it

inner surge
#

I'm looking for an suggestion of how to do a system,
right now we run many instances of the same game mode and players connect to others through world borders, there's a combat system in which if a player quits while in combat he dies, even tho while crossing the border would also be playerquitevent, is there a "channel", in Bukkit, but related to Velocity, where I can detect when a player is disconnecting from the server with his client? and not being sent to another server.
Please if you could give an suggestions, i'd be grateful, ping me when answering
Have a great day y'all

I'm also able to implement a redis channel, would the connection event to another server be called before PlayerQuitEvent?

oblique haven
#

That’s probably a decent way to handle it

agile ore
#

How can I make velocity refresh available commands for a player?

#

Its a permission plugin. Need to refresh them after changing the group of a player.

oblique haven
#

Can declare commands fire more than once to the client? If so that’d be how

burnt dragon
#

vyt: not without the server doing it
fixed: yes, on server change

fossil sundial
#

Go onto a vanilla server and /op yourself. Now you have access to more commands

#

I am just not entirely sure how that works on Velocity atm

oblique haven
#

Like when permissions update, re-send declare maybe

#

It would need to work very differently in Velocity if it were to work

inner surge
#

Should there be an margin error?

oblique haven
#

Since the proxy holds the connection it could go either way, I’d say test it

fossil sundial
#

Disconnect is expected to always occur after the connection is already established successfully to the new server

craggy pecan
#

If you want an easy solution, try to initiate the switch from the backend server (save the data, then send the request to the proxy). Otherwise it will require more complex locking logic

craggy pecan
#

It was discussed in the past, but we decided the permission changes are not a usual occurrence, and a server switch will send an updated tree anyways.

agile ore
#

Hey I'm starting my first Velocity plugin. Does anyone have any resources on using com.velocitypowered.api.proxy.messages? If I understand correctly, this could be used for back and forth communication between a Velocity plugin and say, a Paper plugin? also is this the best approach to do that? Does anyone have any tips? p.s. i have never worked with any other Minecraft proxy servers prior.

agile ore
#

^ disregard. i scrolled up and found some info. feel free to share any tips tho

agile ore
#

Which API version should I be using?

vestal prawn
#

3.1.0 or 3.1.0-SNAPSHOT, it's basically the same

#

1.1.X is older version

agile ore
#

ok ty

exotic brook
#

Hey. I am developing a velocity plugin using IntelliJ IDEA. Does someone have a working configuration for a test environment? I really would appreciate it. 🙂

oblique haven
exotic brook
oblique haven
#

If anything it takes like 5 minutes to configure

#

But you can just use the default

valid anvil
#

Any RedisVelocity plugin existing?

exotic brook
#

I expressed myself unclearly. I am looking for a way to automatically build my plugin and start/restart the velocity server which loads my plugin.

oblique haven
dull flume
#

Is there a way to intercept/listen to player chat packets using the velocity API or a third party plugin? (like with ProtocolLib)

exotic brook
# exotic brook Hey. I am developing a velocity plugin using IntelliJ IDEA. Does someone have a ...

I just created my own gradle task for easy plugin testing. Maybe this is helpful for someone 🙂

plugins {
    id "de.undercouch.download" version "4.1.2"
    //...
}
//...
task runWithVelocity() {
    download {
        src 'https://papermc.io/api/v2/projects/velocity/versions/3.1.1/builds/98/downloads/velocity-3.1.1-98.jar'
        dest layout.buildDirectory.dir('server')
        overwrite false
    }
    copy {
        from layout.buildDirectory.dir('libs')
        into layout.buildDirectory.dir('server/plugins')
        include "*.jar"
    }
    javaexec {
        classpath layout.buildDirectory.file('server/velocity-3.1.1-98.jar')
        workingDir layout.buildDirectory.dir('server')
    }
}
fossil sundial
#

Velocity-api is on the papermc repo. You shouldn’t be attempting to use the full -jar unless you’re trying to mess around in the internals

fossil sundial
#

wait

#

player chat packets?

#

my bad, yes there is a chat event

dull flume
#

But does it include every packet? I need all chat messages sent to players not just the player chat messages. System events from plugins as well.

fossil sundial
#

that isn’t supported. Velocity doesn’t intercept those. For those you’d need to use something like Protocolize

#

you can intercept player -> server with the api but not the other way around

dull flume
#

Ok thank you. I will take a look at Protocolize

young pilot
ashen fiber
#

?

fossil sundial
#

I thought the old velocity nexus was supposed to be deprecated; it should redirect to the paper repo mentioned above
I’ll investigate later

ashen fiber
#

Still points to the old repo

fossil sundial
#

The old website is currently in limbo

#

We are still moving that

#

Noted

ashen fiber
agile ore
#

I used the minecraft-dev plugin for IntelliJ CE to create my velocity plugin. I am using Maven. I am getting these errors in my pom.xml. Does anyone know how I could resolve them?

ashen fiber
fleet sailBOT
bold wharf
#

plugin tried to create a class with an invalid class name

ashen fiber
#

What invalid class name?

#

I am tired so I am not noticing these things.

agile ore
#

Illegal class name "/Lmbda$4" i think

ashen fiber
#

But that does not exist.

#

And nothing is referring to it.

bold wharf
#

The plugin is creating it

#

the plugin did something which caused velocity to do something which caused an error

ashen fiber
#
class MessageOnJoin @Inject constructor(server: ProxyServer, logger: Logger, @DataDirectory val dataDirectory: Path) {
    var joinMessage: Component? = null

    fun loadJoinMessage() {
        val joinMessageFile = dataDirectory.resolveSibling("joinMessage.txt")

        if (!joinMessageFile.exists()) {
            joinMessageFile.createFile()
            joinMessageFile.writeText("Welcome to the server! This is the default join message. You can change it by editing the file joinMessage.txt in the data folder.")
        }

        joinMessage = get().parse(joinMessageFile.readText())
    }

    init { loadJoinMessage() }

    @Subscribe
    fun onConfigReload(event: ProxyReloadEvent): EventTask = EventTask.async { loadJoinMessage() }

    @Subscribe
    fun onPlayerJoin(event: ServerConnectedEvent): EventTask = EventTask.async { event.player.sendMessage(joinMessage!!) }
}
#

Where is the issue... I see no issue anywhere.

agile ore
#

oh, updating intellij fixed my errors.

#

nevermind

agile ore
ashen fiber
#

Kotlin implements Null Safety.
If a variables type definition has a ? at the end that means it could be null.

If a variables accessor has a ? that means only do it if it is not null.
If a variables accessor has a !! that means throw a NullPointerException if it is null.

agile ore
#

ahh that's cool. it all looks foreign to me haha

ashen fiber
#

Really that should be an IllegalStateException, because it should be impossible for that value to be null at that point.

#

Which I would do with joinMessage ?: throw IllegalStateException()

#

?: basically means "if its null, do this"

agile ore
#

interesting

ashen fiber
#

Kotlin has all sorts of cool syntax things that I quite like

#

Like extension functions.

#
fun CommandSource.sendMiniMessage(message: String) = sendMessage(MiniMessage.get().parse(message.trimIndent()))
#

It allows me to "add" my own functions and variables to classes that I don't control.

#

That extension "adds" a function to CommandSource which basically just hides away the nonsense of constructing a Component with MiniMessage.

#

So instead of doing

player.sendMessage(MiniMessage.get().parse("<red>Test"))

I can just do

player.sendMiniMessage("<red>Test")
#

Which is much nicer.

agile ore
#

hmmm.. i still able to build my plugin even though my pom.xml is spitting out errors. i guess if it ain't broke, don't fix lol. But i do need to add some dependencies so we'll see

agile ore
#

So in my Velocity plugin, I have a map of online players where each player points to a PlayerData class with some variables. I need to access these per player variables from the backend-servers as well, sometimes quite frequently (mainly every PlayerDeathEvent and every time a player is damaged by another player). I don't quite understand the limitations of the plugin message API. Would this be an appropriate use of the plugin message API or should I be using something like Redis or memcached instead?

agile ore
#

how do i get the UUID of the player executing a SimpleCommand?

rich hawk
#

cast to player

#

Instanceof first

agile ore
#

ah ty

#

I'm still trying to wrap my head around plugin messaging. If a plugin message is sent to the server by a player (PluginMessageEvent.getSource() instanceof Player) does that mean they're tampering with packets? Or does it mean one of the backend-server's is sending it but associating a player with it? I'm having a hard time finding docs or resources about this stuff (resorting to looking through github projects)

fossil sundial
# agile ore I'm still trying to wrap my head around plugin messaging. If a plugin message is...

Source is where the message came from
If it’s Player then it’s most likely that this player is using mods or hacks that are capable of sending a direct message

Generally if you want to use plugin messaging to communicate between proxy <-> server you need to swallow all messages on the same channel by the user

There’s a reason for that:
Normally plugin messages travel like this:
player -> server
and
server -> player
But you have a proxy in between
player -> proxy -> server
and
server -> proxy -> player

This is how the messages travel if you don’t set them to .handled() on the proxy. By setting a message to handled it stops the message on the proxy:
player -> proxy
and
server -> proxy
So always set them to handled no matter where they’re from unless you’re just watching the data going through

If you just want communication between server and proxy then your source should be instanceof ServerConnection
If you want communication between player and proxy then your source should be instanceof Player

#

Likewise if you want to send a message to the server then your message sink should be the ServerConnection of a player
And if you want to send a plugin message to the user then the message sink should be Player directly

agile ore
#

Awesome thank you for the explanation.

fossil sundial
#

I generally kick/punish players that attempt to use an internal plugin channel to try and do something
Because there are no mods that do anything on my channels and the vanilla client will never touch them you can be sure that something fishy is going on if there is suddenly a message source instanceof player

agile ore
#

fair enough, good idea i guess to disconnect and prevent arbitrary/unneeded network usage.

inner surge
#

Redis is more safe

agile ore
#

im looking into redis at the moment

inner surge
#

Alright great

#

use JedisPool, dont use Jedis directly

#

This way you'll have healthy connections and almost no chance to break any system, depending on the conf of redis server

fossil sundial
#

If you need communication in real-time then you’re better off with plugin messaging

agile ore
#

Well my problem is.. For each online player, I store their ID in a map along with player data that is loaded from a MySQL database when logging in. I need this player data to be accessible from each server. I could serialize each player's playerdata object and store it in Redis. And then deserialize it when accessing it. But I have an event that checks every time 2 players PVP, if they're allied, it will prevent pvp damage between the players and I'm not sure if it's worth setting all of this up only to find out deserializing the player data object everytime PVP occurs would lag out.

inner surge
#

Wait a second

#

You're doing this all just for pvp?

agile ore
#

well, it's complicated

fossil sundial
#

If paper already had api for it you could send the data on login to the server

inner surge
#

Or there's more fields on the data else than related to pvp

#

Although, if you want to use the channels

#

use server.sendpluginmessage

#

and not p

#

this way you'll be a little more secured

#

I use redis on a 400p network on 1.18, I had a way to check if players were online on servers so it was the best way I found
Jedis usually is "real-time" too

#

Depending on how you use it

#

You can for sure serialize & deserialize their data, i wouldn't say its the best way tho

#

One thing is

agile ore
#

they need to be able to send (and accept) ally requests cross-server. which is why i want to "globalize" the player data cache using redis.

inner surge
#

You of course is not going to call any jedis call on the main-thread.

inner surge
#

The concept of it is like plugin messaging

agile ore
#

So they all have access to current valid cached data without constantly querying or polling the mysql database

fossil sundial
#

I’d have done it with a presync login plugin message before login to each server and a plugin message to update data if applicable
Not sure if you really want a redis system for that

agile ore
#

ex: every PvP event

inner surge
#

You're not doing any security thing on the plugin messaging

#

just go with it

agile ore
#

yeah, i need to check player's online as well..i feel like it would be a lot of work to setup plugin messages just to read/write a cache.

inner surge
#

If you're doing this for the pvp

#

there's no need for you to keep that cached on another instance where the player is not online

agile ore
#

that's why i wanted to have one cache by using Redis

inner surge
#

since you're not going to have pvp events because he's offline

#

What you can do is:

agile ore
#

well then what about ally requests.

#

I would like Player A to be able to send an ally request to Player B (on a different server). and if player B accepts, update both player's player data to reflect that change. then if player B hops on Player A's server, they won't be able to PvP

inner surge
#

Keep object cached on actual player instance -> and only there <-

Create your message system using the plugin messaging so you can handle accept, request, deny, and removal of allies through the network while they're online

If you need to check if an player is online on the server, write an online tracker on velocity(create a plugin) that sends plugin message to the servers when a player connects-disconnects of the proxy or prefered instances

#

So on every data change, you already run a statement to update that on the database

agile ore
#

yeah

inner surge
#

You won't have any lag issue with this system if you correcttly manage the used threads

agile ore
#

there's lots of database reading, not writing. so i only use the cache for reading, and when updating the db i update the cache

inner surge
#

and never the main thread on any of those processes.

inner surge
#

First of all, unless you're calling a read a thousand times on the main thread, you won't have any lag issue

#

If you want to check if the player is already an ally

#

Send the ally request

#

check on the cache if the user is already an ally

#

if he is

#

send back an message to the requester, "hey you're already an ally"

#

Both ways work just fine

#

There's no problem in using the database that way, unless you're calling it on the main thread

#

Of course, if you want less requests on the database you'll have to increase the requests on pluginmessaging

#

If you used redis, you'd be serializing deserialzing data everytime it changes either, you'd just decrease the requests on the database to increase the requests on the redis server

#

And risk loss of data

agile ore
#

the database caching is fine i think. my issue is now being able to access this data real-time from different sources. would it be worth the work to setup a central cache using plugin messaging or use redis. but if i use redis i have (lots of de/serializations) and plugin messaging seems like a hacky way to do this.

#

it would be nice if i could store a plain java object and access it kind of like a database, just in real-time.

inner surge
#

It would be worth to run a query to get the data from the database and check what you need to check

#

You don't need a central cache

#

It wouldnt be worth it

#

Not for that type of system

agile ore
#

what if there's 20 players fighting, each hitting each other 4 times a second that's 80 database queries per second to check if any of those player's are allied to eachother. not very good for a real time game. not to mention any other load the database might have at that time from other plugins

inner surge
#

Dudeeeeeeeee

#

nooooooooooo

#

When the player joins

#

you cache his data

agile ore
#

sorry i misunderstood?

inner surge
#

If the player is online you cache his data

#

You don't run sql queries on damages, you'd never be able to do that async and cancel the damage

#

I'm gonna write in plain english

#
Step 1:
Player join,
Load his data from database and cache it on the server(instance he is now)

Step 2:
Write the plugin messaging system where it will be able to make the player become an ally through servers

Step 3:
Save player's data every time it changes, so if player1 sends an ally requests from server1 and player2 receives it on server2, you'll run a query to update the data on the database, if for some reason player2 connects to server1, you'll do step1 to him,
the data cached will be the data on the sql database, which would contain player1 as an ally
#

You're overcomplicating this

agile ore
#

Ohh I get it

inner surge
#

and PLEASE

#

NEVER ever

#

run sql queries on the main thread

#

Always run it async

agile ore
#

So in essence use plugin messaging to queue server caches for updating.

inner surge
#

SQL query is heavy operation, don't ever run it on the main thread

agile ore
#

I use async Dw lol

inner surge
#

But you only keep the player's data loaded on the server he is at the moment

#

not on all instances

agile ore
#

Yes

#

Thanks so much for talking through with me and now I don’t have to rewrite all my code

inner surge
#

From my knowledge that's the best you can have without wasting 10 days writing something

#

And it's a system i've already tested on more than 1k player's at the same moment on a network

#

I hope it helped 🙂

agile ore
#

Yeah the way to go now

twilit timber
#

hello, DisconnectEvent happens when a player leaves a server or just when he disconnects from the proxy?
is there a way to listen for the first one (or just plugin messages from each server?)?

inner surge
#

proxy

#

If you want to detect when a player disconnects from one server to another or connects on first time on the network, go with ServerPreConnectEvent or ServerConnectEvent,
both mave methods of previous server which is Optional<>

plain ledge
#

hi, can anybody tell me how can i make a clickable message on velocity? in spigot I could use textComponent, I don't see such an option here

atomic leafBOT
pearl sandal
#

hi, is is possible to add scoreboard api into velocity?

bold wharf
#

eeeeeerrr

#

your question makes little sense of what you're actually asking

#

can you add one yourself mesing around with packets? yes

#

is there a library for that somewhere? idk

#

is veloity planning to add an api for it? last I knew it was something they planned to do with as much excitement as a sandpaper dil.. nvm

pearl sandal
#

so basically no

#

I need it for player sorting in tablist

fossil sundial
#

both of you; scoreboards are being worked on. I just want an implementation that doesn’t have the issues the bungee impl has

#

and that is, both time-consuming and difficult to design test and deploy

#

Though its not the number one priority its also no dead-last.

ruby jungle
fossil sundial
oblique haven
#

It would probably be best to add velocity support to the aforementioned plugin or just ask the creator to if it’s not open sourced

#

I’d imagine the proxy part is rather small

#

Unless there’s no players on the sub servers - in which case it’d have to use sockets 🤷🏻‍♂️ but I don’t think that’s what it does

#

It does use sockets

#

Last commit was - 7 months ago so I’m unsure if it’s still a thing

violet lion
inner willow
#
    public ProxyServer getProxyServer() {
        return proxyServer;
    }```
this auto-fill getProxyServer does not work with with the below code because it is static.
```java
    public static void globalUpdate() {
        for (RegisteredServer server : Worldmc.getProxyServer()) {
            for (Player player : server.getPlayersConnected()) {
                player.sendPlayerListHeader();
            }
        }
    }```
burnt dragon
#

nobody is stopping you from using dependency injection

#

also, nobody is stopping you from making your own singleton if you're lazy

onyx badger
#

I want to translate this message into English. But it returns me a message in my language (ru_RU). Is it normal?

wooden mauve
#

I actually wanna remove some commands on command suggestion typing /, I see that TabCompleteEvent is only for 1.12.2 and below. What would be the right event for 1.18.1?

bold wharf
#

I mean, generally, do perms properly

#

if you wanna remove commands for earlier versions they need to be removed from the command structure sent to the client

#

but, stuff using perms properly is the proper solution to all of this

wooden mauve
#

I can't, some plugins still show up commands what actually not allowed in perms and I can not replace them at the moment

warm gulch
wooden mauve
#

Thanks, that looks promising. I also would like to do it via perms but I see no way to remove commands like bukkit or vivaversion and other plugins without explicit permissions via perms from command suggestion.

sacred musk
#

Hi, which packet class is responsible for sending tab completion for the commands that exists?

fossil sundial
# warm gulch PlayerAvailableCommandsEvent perhaps?

@sacred musk whatever you’re trying to do here is a bad idea. you should rather edit the command structure with this event. But alas i can’t stop you, the name of the class on velocity is TabCompleteResponse

sacred musk
#

Thanks, I didn't even look at the messages above

fossil sundial
vestal prawn
#

why there is a nokotlin emoji 🤔

ashen fiber
#

Only those who do not understand the awesomeness of Kotlin would dare to use it.

twilit timber
#

hello, simple question.. do I use runAsync here or the method itself will be called in a separate thread when @ subscribe is async=true?

    @Subscribe
    private void heavyTask(ServerConnectedEvent event, Continuation continuation) {
        CompletableFuture.runAsync(() -> {
ashen fiber
#

I thought it was EventTask.async?

twilit timber
#

you can do EventTask or add Continuation as a parameter from what I've read from docs

ashen fiber
#

Never used continuations, so you've lost me now.

icy locust
#

Is there any way to add custom json to a ping response?

inner willow
#

Is it possible to get a registeredServers max player count?

ashen fiber
inner willow
#

Completable future 😒

icy locust
ashen fiber
#

No...

#

Well maybe, it may cause issues though

#

Better off using plugin messaging channels if you wanna send custom data to the client.

inner willow
#

Does MiniMessage not work on velocity?

#

Caused by: java.lang.ClassNotFoundException: net.kyori.adventure.text.minimessage.MiniMessage

ashen fiber
#

Minimessage is not provided

#

You have to include it yourself

inner willow
ashen fiber
#

No

agile ore
#

How do I add tab completion to a SimpleCommand?

#

Nvm, I should have looked through docs first.

paper cosmos
#

wrong channel my bad

ashen fiber
agile ore
#

that's what i use with paper. im just a little bit iffy on implementing it with Velocity

#

oh. it support velocity out of box.... welp lol ill use it now

inner willow
#

Do I have to shade minimessage to use it

ashen fiber
inner willow
#

Is there a method to obtaining a disconnecting players current server?

agile ore
agile ore
inner willow
ashen fiber
#

DisconnectEvent.player.server may work

agile ore
ashen fiber
#

But DisconnectEvent can have weird behaviour

agile ore
#

but that would only be for when the player disconnects from the proxy, you would also have to use ServerConnectedEvent to get when player switches servers. Otherwise, if possible, i would just implement what your doing into a plugin on the servers itself

ashen fiber
#

Alternatively you could keep track of the players and server and then check disconnects that way.

inner surge
#

You use ServerConnectEvent

#

For proxy, you use DisconnectEvent

#

Oh yeah, just like Elmig said

#

Btw, @agile ore did you got the combat sys working? you asked below ^^

agile ore
#

im working on it right now (hard to find time lol). so i got all the commands /ally <player> | /allyaccept, etc, etc running on a Velocity plugin. Then for every player that is affected by the command, i'll send a plugin message to all servers to saying hey, if this player is on your server (is cached), REFRESH THEIR PLAYER DATA! I just have to code the plugin message part of it now

atomic leafBOT
#

Please send large files/logs to a pastebin

inner willow
agile ore
#

"Header" case-sensitive?

#

Try getString("header") and besides, this velocity-dev. Toml4j is a whole other project.

inner willow
# agile ore "**H**eader" case-sensitive?

Sorry -

        for (RegisteredServer server : Worldmc.getProxyServer().getAllServers()) {
            String serverName = server.getServerInfo().getName();
            placeholders.put("server", serverName.substring(0, 1).toUpperCase() + serverName.substring(1));
            placeholders.put("players", String.valueOf(server.getPlayersConnected().size()));

            for (Player player : server.getPlayersConnected()) {
                placeholders.put("player", player.getUsername());

                player.sendPlayerListHeader(MiniMessage.get().parse(Worldmc.getConfig().getString("header"), placeholders));
                player.sendPlayerListFooter(MiniMessage.get().parse(Worldmc.getConfig().getString("footer"), placeholders));
            }
        }```
Besides the error has switched up on me. `java.lang.NullPointerException: Cannot invoke "String.replace(java.lang.CharSequence, java.lang.CharSequence)" because "richMessage" is null`
fossil sundial
#

Error is caused by .parse(null

#

So the null pointer from your config didn’t change

#

Not sure how you’re doing config but you may need to retrieve the config section first

inner willow
#

I'm inexperienced with toml, what do you mean retrieve the config section

agile ore
inner willow
#

There is almost no difference between the documented quickstart and my ver

agile ore
#

then that's an issue with toml, not velocity

bold wharf
#

Bu, you have no config option called header

agile ore
#

"Non-existent keys return null." Debug your file loading and dump your Toml config into a console 🤷

bold wharf
#

you have an option called header under the global playerlist section

#

but, not under the root of the config itself

agile ore
#

there ya go

inner willow
#

Thank you both.

inner willow
#

Is there a 'postDisconnect' event?

Or a way to get server.getPlayersConnected() after the disconnect event has completed

agile ore
#

what are you trying to do?

inner willow
agile ore
#

just remove disconnected player from tab list

inner willow
bold wharf
#

using teams, yes

inner willow
bold wharf
#

Well, you don't

agile ore
#

.sort ?

bold wharf
#

sort is useless, order in the tablist is handled by the client

agile ore
#

oh

#

Does anyone have any advice on bridging player inventory/armour/health/hunger/enderchests/XP between servers?
if i use async MySQL to load/upload data on player join/quit I imagine that in some cases, it might to result in catastrophe.

bold wharf
#

well, I mean, if you have full control over the server switch process, yes

#

But, that gets more nuanced into state handling, etc

#

trick people use is to basically just delay a few seconds on the other end, which, blows and has its own set of issues, but, er, outside of other things like keeping stuff sync'd up over a message broker in real time, etc, glhf

agile ore
#

yeah, im realizing this headache now. for every pro, there seems to be an equal con. would it be practical to sync the playerdata folder using the network somehow? or is that a bad idea?

bold wharf
#

no

#

the entire reason why using mysql creates issues there creates issues with the entire process in general

#

you start joining the new server before you leave the old one fully

agile ore
#

nods head

inner willow
bold wharf
#

I mean

#

you have to use teams

#

so, either you send the packets out yourself or use some library, or, you don't

dusk timber
#

why build bytes?????

#

./gradlew build to run the full build cycle.

agile ore
#

what error does it give?

dusk timber
#

i jusc compile velocity and run it

#

this guide

agile ore
#

output jar is probably in proxy/build/libs

dusk timber
#

I RUN IT!!!!

#

gradle 7.3.1 (and 7.3.3 too it bug)

agile ore
fossil sundial
#

^ make sure you grab the -all.jar
if there is none with that ending then it didn’t compile correctly

agile ore
#

Hi! Is there a alternative to BungeeCord's ProxiedPlayer#getDisplayName()? Or is that Player#getUsername()?

fossil sundial
agile ore
#

oh ok... Well thanks anyway!

#

Wait.. Player.getUsername() will return the player's username, right?

valid gazelle
#

is there a way to enable debug logging in the console? i'm using Logger#debug to send debug messages but i can't see them

inner willow
#

Scoreboard api?

fossil sundial
inner willow
vestal prawn
#

Kind of weird but it works

burnt dragon
#

there is nothing wrong with using static finals in utils classes

vestal prawn
#

Yes but static method are already finals

burnt dragon
#

and that's a variable?

#

static variables aren't final unless you add the final modifier

vestal prawn
#

lol yes

#

i misread im on phone half the screen is hidden i didn't see it was a variable

agile ore
#

This is how i would send a plugin message, right?

#

I've also never used Optional<> before. Does that look right?

reef jacinth
#

That looks fine

onyx badger
#

Does GlobalTranslator in Velocity replace en_US with my default one? I'm trying to translate velocity.error.cant-connect to en_US but I'm getting a message in another language. Other languages ​​from velocity.l10n work correctly

burnt dragon
#

well, do the other translations exist in the global translator?

onyx badger
#

yes. problem occurs only when translating to en_US

onyx badger
#

before launching Velocity, I changed the default language to en_US. now everything works correctly.
Anyway, it shouldn't be like that, right? (I'm talking about the problem that I described above)

plain ledge
#

Can I use hover and click in one message when using MiniMessage?

burnt dragon
#

yes

plain ledge
#

how?

burnt dragon
#

add a hover tag, follow it with a click tag

plain ledge
#

Can I just post a hover tag here?

burnt dragon
#

yes

plain ledge
#

thanks

paper thistle
#

How do you actually "create?" a KickResult event so I can actually do setResult() on a KickEvent?

burnt dragon
#

for example KickedFromServerEvent.DisconnectPlayer.create(whatevr)

#

with all the relevant subclasses

paper thistle
#

Cool, cheers

plain ledge
#

is there any way to use broadcast? I don't see anything about it in MiniMessage

burnt dragon
#

minimessage doesn't have a concept of broadcasting

#

if you need to send a message to all players, i believe ProxyServer implements Audience so you can use the sendMessage method on that

paper thistle
#

Where might I intercept this for a better message of my own?

burnt dragon
#

instead of fireAndForget you can use the connect method which leave you responsible for error handling

paper thistle
#

well, I'm using the plugin-level bungee send

#

in that case

burnt dragon
#

idk if you can do anything about that from solely the plugin side

#

unless you had some custom proxy plugin handling a custom plugin message transfer request

paper thistle
#

Yeah I already use rabbit for lots of comms, so maybe i'll just use that to make the proxy do all server connections

#

so i can have better control

fossil sundial
paper thistle
#

👍 I'll just do the above ^

ornate escarp
#

Hey all, is there a method of real time communication between a Paper plugin on a server and a Velocity plugin on a velocity server? My solution years before was UDP messaging. Thanks!

fossil sundial
ornate escarp
plain ledge
#

can I use server.SendMessage () to send a message to players on all servers?

burnt dragon
#

if server is ProxyServer then yes

polar sentinel
#

is there an event that fires when a server is started?

coarse topaz
#

For a backend server? no

polar sentinel
#

as in on the proxy server

#

I guess I could announce it from the paper servers

coarse topaz
#

Right, you don't know when a backend server (paper in this case) has started, you can use a messaging service if you need

reef tiger
#

Can I cast ChannelMessageSource to Player?

ornate escarp
#

How can I determine if a message originated from a server (velocity or paper) or player for filtering please?

low crypt
#

is there any way to edit the locales without updating the jar?

fossil sundial
#

Velocity will include it once it’s in adventure proper
To quote Kash on that:
“we plan to merge minimessage into the main adventure repository for the 4.10.0 release”
When that has happened and velocity has updated then it will be included

low crypt
#

ok ty!

fossil sundial
low crypt
fossil sundial
#

You can edit the project translations directly and compile it yourself after

#

But that’s pretty much the only way besides editing the jar

low crypt
#

okay thanks

ornate escarp
fossil sundial
#

If you’re on the server then you can’t know where the message came from
The proxy is transparent to the server;
You can probably check if the player is connected to a proxy using the bungeecord api to query something like the current server
But other than that there isn’t much you can do

ornate escarp
#

Alright, thanks so much.

#

I was overthinking it, all players need to go through Velocity so won't be directly on the server.

fossil sundial
#

You may want to encrypt your traffic on both sides or sign it if you’re concerned. Put a token in your config that’s used to do that, it’s what velocity does to do modern/bungeeguard forwarding

ornate escarp
fossil sundial
#

A kind of secure proxy messaging solution is also on the table for the next gen of velocity forwarding

#

But that’s something for the far future

narrow smelt
#

Hi, I would like to know if there is a way to get access to guice injector of velocity so I can create my own objects with injector.getInstance()

warm solar
#

How can I replace the @version@ string with gradle kts?

proper steeple
#

ContentFilterable#expand can do the trick

warm solar
#
tasks.processResources {
    expand("version" to parent!!.version)
}
``` maybe this is in the wrong task
rich hawk
#

might need to add the @@?

warm solar
#

didnt help :/

warm solar
#

nvm i had typo

neon shuttle
#

This plugin will help you to replace the version in the @Plugin

#

Or if you want to replace in the .json

#

you could use

processResources {
  filesMatching(List.of("yourFile.json")) {
          expand("version" to project.version)
  }
}

and replace @version@ with ${version}

woven hawk
#

velocity has any native configuration loader?

thick bramble
#

configurate 3

woven hawk
#

I can't find in the docs

thick bramble
woven hawk
#

Right, thanks!

agile ore
#

Hey guys, how can I dispatch a command?

#

I saw I could use server.getConsoleCommandSource() to get the console command source

agile ore
#
        LiteralCommandNode<CommandSource> helloNode = LiteralArgumentBuilder
            .<CommandSource>literal("test")
            .executes(context -> {
                Component message = Component.text("Hello World", NamedTextColor.AQUA);
                context.getSource().sendMessage(message);
                return 1; // indicates success
            })
            .build();
valid gazelle
#

instead of having to use a switch

craggy pecan
#

^ you generally want a (brigadier.)Command lambda function per executable node in the tree. Let Brigadier do the parsing logic for you

agile ore
#

Oh that’s great

inner skiff
#

How do i get the version the player is? in my plugin i have some messages and i want to know if the player is in a version after 1.16 to use rgb colors in my messages, how can i get to know the version of the player?

bold wharf
#

er, check if the API exposes the protocol version on the player?

fossil sundial
inner skiff
#

yes

agile ore
analog dew
#

Velocity natively supports the BungeeCord messaging protocol, so any BungeeCord plugin messages you would normally send from your backend to Bungee will work the same with Velocity

agile ore
#

sweet, okay. thanks!!

inner skiff
#
player.playSound(Sound.sound(Key.key("minecraft:entity.enderdragon.death"), Sound.Source.MASTER, 1.0f, 1.0f), Sound.Emitter.self());

Any clue why this doesn't work?

rich hawk
#

.

inner skiff
#

a

wary tiger
#

This happens all too frequently. A solution ought ot be devised

warm gulch
#

audiences fail silently by design

wary tiger
#

Yes, I'm well aware

burnt dragon