#velocity-dev

164 messages · Page 12 of 1

agile ore
#

Thank you for your answer. Is there a documentation on the Velocity site?

burnt dragon
#

you can find good docs on their github wiki

agile ore
#

Hello, i can't deny the ChatResult with a message?

oblique haven
#

but afaik there's no "chat result" packet which even exists

agile ore
#

That's what I did, but I find it strange that there is a method to accept with a message but not to refuse with a message lol

#

Thanks you !

oblique haven
#

"accept with a message"?

#

you mean the message which is sent?

agile ore
oblique haven
#

right - this overrides what the player sent

agile ore
#

Oh right, I misunderstood the method

real kelp
#

i just created a fresh velocity project in intellij with the mc extension, why am i getting all of these errors?

bold wharf
#

try a build

real kelp
#

[ERROR] Failed to execute goal on project me.bubbarob19: Could not resolve dependencies for project testvplugin:me.bubbarob19:jar:1.0-SNAPSHOT: Failure to find com.velocitypowered:velocity-api:jar:3.1.1 in https://repo1.maven.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]

bold wharf
#

you have a dep which you don't have available

real kelp
#

velocity version 3.1.1 doesn't seem to work

#

3.0.1 worked but idk how outdated that is

#

and then its all of these maven plugins that arent working properly

fleet sailBOT
real kelp
#

not sure how to fix any of this considering idk what any of it does lol

bold wharf
#

(your pom is also invalid, name shouldn't have a . inside of it)

real kelp
#

ah it seems the repo they put in the mc intellij extension is outdated

#

ill see if i can update the plugin, thanks

bold wharf
#

yea, fixing the name and the repo and it builds

wanton tangle
#

question: is there a license requirement when using the velocity-api to develop plugins?

#

or can I choose any license for my plugin

craggy pecan
#

Most "standard" licenses will work, the API is MIT-licensed

wanton tangle
#

perfect

agile ore
#

Does anyone know how can I make a "rejoin" thing on velocity?

#

So the player gets kicked from current server and immediately gets reconnected

fossil sundial
agile ore
#

Okk

jovial timber
#

How does one do error handling for something like this:

ConnectionRequestBuilder connection = p.createConnectionRequest(server.getServer("event").get());
connection.connect();
sour current
#

.connect returns a future with a result

flint forge
#

What’s the easiest way for me to have global variables between servers

#

Just a database? Or

sour current
half locust
#

zestarr: yeah DB or messaging service or some combination thereof

flint forge
#

Ok ty, and if I want to send a player to a server do I need to import velocity via maven into my spigot plugin?

#

Or how does that work? Never used velocity

sour current
#

if it's a plugin that runs on the backend you can use the bungee messaging channel

flint forge
#

Ok ty!

tough dock
#

is there any good tutorials/resources to start developing plugins for velocity?

sour current
tough dock
#

thank you ❤️

nova sparrow
#

look at my source code i handle it

tough dock
#

im quite noobie, can a velocity server run a bungee plugin and vice versa?

bold wharf
#

no

tough dock
#

oh

#

ok

bold wharf
#

There is a plugin which triiiiiiiess that, but, unsupported, expect bugs, etc, etc

nova sparrow
#

i think i might have seen a plug-in that can try it

#

yeah i can’t imagine it’d be bug free

tough dock
#

good intel, thanks 😛

mystic horizon
#

Hello! How can i cancell all player commands?
I try to use something like this, but it is not work for me

public void onPlayerExecuteCommand(CommandExecuteEvent e) {
if (PlayerData.INSTANCE.isAuthorized(player.getUsername())) return;

    e.setResult(CommandExecuteEvent.CommandResult.denied());

}

mystic horizon
#

Yes

#

for debug, i add some lines of logs. I see logs in console. but command not canceled

nova sparrow
#

probably an issue with velocity not cancelling the forwarding of those commands

#

i think i’ve experienced something of the sort before?

rough tangle
#

Sorry ahead of time I am new to futures. I am trying to monitor the result of sending a player to a server. When I look at the future when it completes is always say CONNECTION_IN_PROGRESS. I'd like to be able to see when it hits the SUCCESS state as well.

connection.thenAccept(result -> System.out.println("Result: " + result.getStatus().name()));```
This is always the result I never am able to see the flow finish.
```Result: CONNECTION_IN_PROGRESS```
graceful vault
#

I was wondering if it was possible to determine if a player was connecting via a forge client or via a vanilla client?
Player.getModInfo() is not present when joining via forge, player.getClientBrand() just returns null in either cases.

fossil sundial
#

1.12.2 and older use this system, but you’ll have to wait till the first server join is complete

#

1.13 and newer you’ll have to register and listen to the appropriate login plugin channels yourself

#

before that it’ll always be null

fickle grail
fossil sundial
#

Either someone else does it or it’s gotta wait

#

Sorry

fickle grail
half python
#

Can I be sure that
LoginEvent is fully completed (whatever how long it takes)
until
ServerConnectedEvent is fired for a player? because that doesnt seem to be the case

fossil sundial
#

Yes unless you have a plugin or you yourself are calling a connection request in this specific event

willow bone
#

After C->S encryption response, and the ACK from the server, what packet is expected next from the server? I can't seem to find the doc

willow bone
craggy pecan
#

Or do you mean the first packet on the play state?

nova sparrow
#

Using Component.translatable, does it parse & as hex/formatting or whatnot?

#

Or is it only the funny gambit symbol

rich hawk
#

neither

#

it doesn’t parse anything afaik

nova sparrow
#

Any idea how I can make it do so

rich hawk
#

not

nova sparrow
#

I've done it in the past, but with using .translatable

rich hawk
#

don’t use legacy

nova sparrow
#

wdym by that

rich hawk
#

translatable are meant to be text only i think, you do the formatting yourself

fossil sundial
#

^

nova sparrow
#

all g

sudden ridge
#

Is there any way for a backend server plugin to send a message to all velocity proxies?
I'm using Herochat which sends chat messages through the messaging channel but only for the proxy the message originated from and I was wondering if that way you could get cross-proxy messages 😅 Just a very wild idea that crossed my mind :D

fossil sundial
#

As for 1.19 and newer this isn’t working cause the api for it is missing; see the 3.1.2 milestone on GitHub for that; it’s still indev

sudden ridge
fossil sundial
#

Well you’d need a plugin on the proxies

#

And one on the servers

sudden ridge
sudden ridge
tawdry sky
#

Any advice on this error?

#
[15:54:06 ERROR]: Couldn't pass ServerPreConnectEvent to lendnet
java.util.NoSuchElementException: No value present
        at java.util.Optional.get(Optional.java:143) ~[?:?]
        at lendmark.net.listeners.ServerSwitch.ServerPreConnectEvent(ServerSwitch.java:39) ~[?:?]
        at lendmark.net.listeners.Lmbda$40.execute(Unknown Source) ~[?:?]
        at com.velocitypowered.proxy.event.UntargetedEventHandler$VoidHandler.lambda$buildHandler$0(UntargetedEventHandler.java:47) ~[velocity.jar:3.1.2-SNAPSHOT (git-662fbc4e-b159)]
        at com.velocitypowered.proxy.event.VelocityEventManager.fire(VelocityEventManager.java:598) ~[velocity.jar:3.1.2-SNAPSHOT (git-662fbc4e-b159)]
        at com.velocitypowered.proxy.event.VelocityEventManager.lambda$fire$5(VelocityEventManager.java:479) ~[velocity.jar:3.1.2-SNAPSHOT (git-662fbc4e-b159)]
        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) [?:?]```
#
            RegisteredServer server1 = server.getServer("lb01").get();
            RegisteredServer server2 = server.getServer("lb02").get();

            if (server1.getPlayersConnected().size() > server2.getPlayersConnected().size())
                Utils.sendPlayerToServer(server2, player);
            else if (server1.getPlayersConnected().size() < server2.getPlayersConnected().size())
                Utils.sendPlayerToServer(server1, player);
            else {
                int min = 0;
                int max = 1;
                int random_int = (int) Math.floor(Math.random() * (max - min + 1) + min);

                if (random_int == 1) {
                    Utils.sendPlayerToServer(server1, player);
                } else {
                    Utils.sendPlayerToServer(server2, player);
                }
            }```
lethal garnet
#

check ifpresent on any optional you use

tawdry sky
burnt dragon
#

what do you think the .get() calls at the beginning do

#

(hint: read the javadoc)

tawdry sky
#

I think

burnt dragon
#

it also clearly isn't working with it

lethal garnet
#

read the javadoc

tawdry sky
#

but throws the error

lethal garnet
#

because it doesn’t work?

tawdry sky
#

It works correctly

lethal garnet
#

then it’s placebo

burnt dragon
#

well then why are you asking for support if it's working fine

tawdry sky
#

..because of the error

burnt dragon
#

so it isn't working....

tawdry sky
#

It is, but spams the logs

burnt dragon
#

i give up

tawdry sky
#

Okay, let's say it isn't

#

ohh I think I get it now

lethal garnet
#

what do you get

tawdry sky
lethal garnet
#

also, you aren’t checking if your optionals are present

tawdry sky
#

That's what I'm saying

#

I added a check for if there even is a server present

#

might work now

#

I take that back

#

Still throws the error

#
        if(player.getCurrentServer().isPresent()) {
            if (player.getCurrentServer().get().getServerInfo().getName().equals("asdasdasd")) {
                RegisteredServer server1 = server.getServer("lb01").get();
                RegisteredServer server2 = server.getServer("lb02").get();

                if (server1.getPlayersConnected().size() > server2.getPlayersConnected().size())
                    Utils.sendPlayerToServer(server2, player);
                else if (server1.getPlayersConnected().size() < server2.getPlayersConnected().size())
                    Utils.sendPlayerToServer(server1, player);
            }
        }```
#

And yes lb01 and lb02 exist

lethal garnet
#

send a paste link to your exception

#

and what line the line the exception occurs at is

tawdry sky
#

Still the same thing

#

And I don't see the line anywhere

#

NEVERMIND

lethal garnet
#

what is line 38 of ServerSwitch.java:39

tawdry sky
#

HOW AM I SO STUPID

#
        if (player.getCurrentServer().get().getServerInfo().getName().equals("ob-main") && !event.getOriginalServer().getServerInfo().getName().equals("ob-main")) {
            player.sendMessage(Component.text("§eUnloadujem pack.."));
            player.sendResourcePack("https://lendmark.blob.core.windows.net/lendmark/default.zip");
        }```
#

kill me, please

lethal garnet
#

don’t worry, everyone makes mistakes

tawdry sky
#

lmao

#

Fixed

lethal garnet
#

have fun developing on velocity!!

tawdry sky
#

Thank you :D

fossil sundial
tawdry sky
fossil sundial
tawdry sky
fossil sundial
#

So you can track it easily

tawdry sky
#

Neat!

fossil sundial
#

That was the whole idea behind this

tawdry sky
#

I'm just glad I got this stupid bug fixed

#

It's been like that since december and I hate it

fossil sundial
#

Technically you should still check isPresent() before .get()

tawdry sky
#

I am now

#

That was the bug

fossil sundial
#

The optionals are gonna be replaced with Nullable values on polymer

#

No reason to have the extra overhead

tawdry sky
#

Yeah

fossil sundial
#

Just coming from bungee where values can be randomly null without documentation we thought we’d be clearer

tawdry sky
#

Also, one more question. I've been trying to move over our chat related stuff over to the proxy, but the formatting doesn't seem to work. Chat filter works fine.

fossil sundial
#

For 1.19?

tawdry sky
#
public class Chat {

    ProxyServer server;
    public Chat(ProxyServer server) {
        this.server = server;
    }

    @Subscribe
    public void ChatEvent(PlayerChatEvent event) {
        Player p = event.getPlayer();

        if(!p.getCurrentServer().get().getServerInfo().getName().contains("ob")) {
            String color = "§7";

            if (p.hasPermission("chatformat.whitecolor"))
                color = "§f";

            String prefix = "§f";

            if(p.hasPermission("group.creeper"))
                prefix = "§2§lCreeper";

            if(p.hasPermission("group.wither"))
                prefix = "§8§lWither";

            if(p.hasPermission("group.dragon"))
                prefix = "§d§lDragon";

            if(p.hasPermission("group.youtube"))
                prefix = "§f§lYou§c§lTube";

            if(p.hasPermission("group.helper"))
                prefix = "§9§lHelper";

            if(p.hasPermission("group.moderator"))
                prefix = "§b§lMod";

            if(p.hasPermission("group.builder"))
                prefix = "§a§lBuilder";

            if(p.hasPermission("group.admin"))
                prefix = "§c§lAdmin";

            if(p.hasPermission("group.majitel"))
                prefix = "§a§lMaji§2§ltel";


            String format = prefix+color+p.getUsername() + "§8» " + color + event.getMessage();

            event.setResult(PlayerChatEvent.ChatResult.message(format));
        }

        Pattern pattern = Pattern.compile(String.join("|", Main.badwords), Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(event.getMessage());
        boolean found = matcher.find();

        if (found) {
            //p.sendMessage("§c§m-----------------------------------------------------");
            //p.sendMessage("§cNadávanie a obchádzanie chatového filtru je proti pravidlám.");
            //p.sendMessage("§cAk sa pokúsiš o obchádzanie filtru, budeš umlčaný!");
            //p.sendMessage("§c§m-----------------------------------------------------");

            p.sendMessage(Component.text("" +
                    "§c§m-----------------------------------------------------\n" +
                    "§cNadávanie a obchádzanie chatového filtru je proti pravidlám.\n" +
                    "§cAk sa pokúsiš o obchádzanie filtru, budeš umlčaný!\n" +
                    "§c§m-----------------------------------------------------").clickEvent(ClickEvent.openUrl("https://lendmark.sk/pravidla")));

            //p.playSound(p.getLocation(), Sound.BLOCK_ANVIL_PLACE, 10, 1);
            p.playSound(Sound.sound(Key.key("anvil_place"), Sound.Source.BLOCK, 1f, 1f));
            event.setResult(PlayerChatEvent.ChatResult.denied());
        }
    }```
tawdry sky
tawdry sky
fossil sundial
#

Oh yea that’s a bug

#

Will be fixed soon

tawdry sky
#

Ah okay, thought I was doing something wrong

#

Thx

fossil sundial
#

Also the audio methods won’t work

tawdry sky
#

Yeah, I saw KEK

fossil sundial
#

We don’t implement those. They’re in there because adventure has them

tawdry sky
#

Ah, okay

fossil sundial
#

It’s out of spec to throw an exception

#

So we just don’t do anything

tawdry sky
#

Guess I'll have to live without BLOCK_ANVIL_PLACE

#

Another thing, is there some Velocity alternative to this?

#
            String color = "§7";
            if (p.hasPermission("chatformat.color"))
                e.setMessage(ChatColor.translateAlternateColorCodes('&', e.getMessage()));

            if (p.hasPermission("chatformat.whitecolor"))
                color = "§f";

            String format = papi+color+"{PLAYER_NAME} §8» "+color+"{MESSAGE}";

            format = format.replace("{PLAYER_NAME}", p.getName());
            format = ChatColor.translateAlternateColorCodes('&', format);```
fossil sundial
tawdry sky
fossil sundial
#

Adventure has a legacy chat serializer

tawdry sky
tawdry sky
fossil sundial
#

It would work for what you’re doing here

#

But you should really take a look at minimessage

#

It’s new in 3.1.2

tawdry sky
#

(in the replace chat messages thing case)

fossil sundial
tawdry sky
#

It's a perk you can buy with a rank (since I prefer to not do p2w perks)

steady trellis
fossil sundial
#

Yea for that the legacy component serializer works

steady trellis
#

i thought 1.19 included MM auto parsing & and §?

tawdry sky
steady trellis
#

maybe only in paper

steady trellis
fossil sundial
steady trellis
fossil sundial
steady trellis
steady trellis
#

shows me outdated versions of adventure api instead

fossil sundial
steady trellis
#

ah xD

fossil sundial
#

Yes

tawdry sky
#

I'm a bit lost

#
            if(p.hasPermission("chatformat.color"))
                event.setResult(LegacyComponentSerializer.legacyAmpersand().deserialize(event.getMessage()));```
#

It's yelling at me that it wants a TextComponent, which if I do that it starts yelling at me that it wants a chat result

steady trellis
#

one sec

#

time to pull up JD unless five ninjas me

rich hawk
tawdry sky
#

Wait I might have it

atomic leafBOT
steady trellis
#

i assume

#

for the setResult

tawdry sky
#
               event.setResult(LegacyComponentSerializer.legacyAmpersand().deserialize(PlayerChatEvent.ChatResult.message(event.getMessage().toString())));
#

also demands a text component

#

well now it wants a string

#

god damn

steady trellis
#

do

#

event.setResult(ChatResult.message(legacycomponent...))

tawdry sky
#

I just realised that may have been useless

#

This is what happens

#
            String format = prefix+color+p.getUsername() + "§8» " + color + event.getMessage();

            event.setResult(PlayerChatEvent.ChatResult.message(format));```
steady trellis
#

yes so now

tawdry sky
#
            if(p.hasPermission("chatformat.color"))
                color = LegacyComponentSerializer.legacyAmpersand().deserialize("&").toString();

            if (p.hasPermission("chatformat.whitecolor"))
                color = "§f";
steady trellis
#

surround format with the legacycomponentserializer

tawdry sky
#

so how about this?

#

I guess

steady trellis
#

W

tawdry sky
#

I get what you're saying now

steady trellis
#

ye

steady trellis
#

deserializing & only i mean

#

but i think u know how it works now

#

good luck sir

tawdry sky
#
            String format = prefix+color+p.getUsername() + "§8» " + color + event.getMessage();

            if(p.hasPermission("chatformat.color")) {event.setResult(PlayerChatEvent.ChatResult.message(LegacyComponentSerializer.legacyAmpersand().serialize(format)));} else {event.setResult(PlayerChatEvent.ChatResult.message(format));}

steady trellis
#

use i believe

#

PlainTextComponentSerializer

#

for the else

#

that will keep it plain with no colors or decorations iirc

tawdry sky
#

Won't that reset the prefixes and shit?

steady trellis
#

hmmm

#

well you could do this

#

so get the legacycomponentserializer

#

serialize the prefix and formatting etc

#

then u can append another component

#

in which case u can append the message

#

so legacycomponentserializer, serialize prefix, formatting, etc,. then append plaintextcomponentserializer and serialize the message

rich hawk
#

if you’re hard coding the format why not just use components

tawdry sky
#

It's something new to me

steady trellis
#

iirc its

atomic leafBOT
steady trellis
#

.replaceText(lambda -> lambda.matchliteral(..)) or something like that

#

its pretty straightforward

#

u can match regex or literal

tawdry sky
#

I meant variables

#

e.g. p.getUsername() ext.

steady trellis
#

wym

tawdry sky
#

For example in that context with the chat formatting

steady trellis
#

tawdry sky
#

Because in a String all you need to really do is "asdasd" + p.getUsername() and it's there

#

not sure if that were to work with components

#

That's why I've tried avoiding them in the past

reef jacinth
#

No, you can't, you would use append to combine multiple components together.

steady trellis
#

if i remember correctly, replacing would like like

String format = "%prefix% %username%: %message%";
Component component = LegacyComponentSerializer.legacyAmpersand().deserialize(format).replaceText(config -> config.match("%prefix%").replacement(prefix))```
#

i don't remember tho

#

unsure if you have to do replaceText per each placeholder

tawdry sky
#

I think I'll cancel that VIP perk

#

Thanks tho

steady trellis
#

you don't have to do it that way, there's always

#
String format = prefix + username;
Component formatComponent = LegacyComponentSerializer.legacyAmpersand().deserialize(format);
formatComponent = formatComponent.append(PlainTextComponentSerializer.plainText().deserialize(event.getMessage());
event.setResult(ChatResult.message(formatComponent));```
tawdry sky
#

interesting

steady trellis
#

si

tawdry sky
#

so this would (theoretically) replace the & in the things?

nova sparrow
#

Using a ComponentSerializer, how can i serialize a translatable component (add color from hex etc)

steady trellis
#

plain = well, plain

#

legacy will format msgs with & or § depending if you use legacyAmpersand or legacySection

#

legacyAmpersand is &

#

so as you see on the 2nd line, we deserialize the formatting, which will format the prefix and username assuming they contain & and §

tawdry sky
#

wait

steady trellis
#

for the 3rd line, we append a plain message (the message sent.. i think?)

tawdry sky
#

wouldn't it be easier to just replace all & with § for String color?

steady trellis
#

no because either way it is legacy

#

so even with § you'd have to use legacycomponentserializer, but use legacySection

tawdry sky
#

Yeah

#

Okay, thanks!

steady trellis
#

Prayge good luck

#

remember to check out adventure's javadocs and other documentation as well

atomic leafBOT
nova sparrow
#

How can I apply a serializer to a TranslatableComponent

steady trellis
#

sorry chief, never used translatable

#

what are you trying to do

tawdry sky
#

haha maybe this will work

#
            if(p.hasPermission("chatformat.color")) {
                if(event.getMessage().contains("&")) {
                        format.replace("&", "§");
                }
            }```
#

will make it a component later

#

my brain stopped working about 10 minutes ago

steady trellis
#

and also

#

if someone sends a message

#

i.e.

#

they're like hi i like this & that

#

then it will replace & with §

nova sparrow
#

If thats what you're struggling wth

tawdry sky
tawdry sky
steady trellis
#

there's no advantage to replacing it because it has to go through the legacycomponentserializer anyways

#

the serializer will handle all the formatting for you

nova sparrow
#
            if(p.hasPermission("chatformat.color")) {
                if(event.getMessage().contains("&")) {
                        VelocityChat.color(message);
                } else {
                        Component.text(message);
                }
            }
#

I'd use something like that

#

obviously thats not finished but you get the jist

tawdry sky
#

Yeah

#

I'll finish it later

#

I guess

#

It's like 40 degrees outside

steady trellis
nova sparrow
#
    private static final LegacyComponentSerializer serializer = LegacyComponentSerializer.builder().character('&').hexCharacter('#').hexColors().build();

    public static TranslatableComponent translatable(String key) {
        return (TranslatableComponent) serializer.deserialize(serializer.serialize(Component.translatable(key)));
    }
#

this feels very wrong

steady trellis
#

what are you trying to do

nova sparrow
#

Just apply hex colors and such to a translatable component

#

And return it as a TranslatableComponent

steady trellis
#

ahh i see

#

is it not working?

nova sparrow
#

Can't even tes it

steady trellis
#

errors?

nova sparrow
#

Having some super strange issue in help channel

#

nah just something in velocity bugging out for a few people

#

Either that or my environment

steady trellis
#

are you running

#

viaversion?

nova sparrow
#

Yes

steady trellis
#

is it up to date?

nova sparrow
#

I uninstalle it

#

Yes

#

Its not via

steady trellis
#

is your velocity up to date?

nova sparrow
#

It's not a plugin issue

#

its an internal issue

#

I've already talked with Five about it

#

its super weird

steady trellis
#

what is on your backend?

#

protocollib?

#

you tried without plugins

#

and all up to date server softwares?

#

paper is up to date and velocity?

nova sparrow
#

Yeah latest everything

#

Weird thing is it just stopped working properly after a restart

steady trellis
#

and without your plugin does it work?

nova sparrow
#

Yes I obv tested that

steady trellis
#

so your plugin is causing the issue except it is an internal issue

#

are you shading adventure by any chance?

#

into your plugin

nova sparrow
#

No

#

What

#

I told you its not a plugin issue

#

it is literally just velocity

steady trellis
#

yes, but you mentioned you tested without your plugin

#

so i interpreted that as

nova sparrow
#

Ive tested with no plugins

steady trellis
#

"it works without my plugin but not with it"

#

ah

#

gotcha

steady trellis
#

hm

nova sparrow
#

Yea

steady trellis
#

have you tried letting your config regenerate?

nova sparrow
#

Looks like a very common rising issue

steady trellis
#

or a fresh velocity install

#

no idea then

nova sparrow
#

Few other people have had this today alone

steady trellis
#

rip

nova sparrow
#

Me and a friend who was running a local env, as well as another user

#

All the same issue and no solution has been found, nor the cause of it

#

Regenerating the config does nothing

#

Same issue

#

its really strange

steady trellis
#

rip very weird

nova sparrow
#

Also still have no clue about applying the RGB and whatnot to a translatable component

fossil sundial
#

What are you even trying to accomplish here
I don’t know of a single part the velocity api has that doesn’t accept a generic component as parameter

nova sparrow
#

Well I want to be able to return a TranslatableComponent, with RGB and whatnot applied

fossil sundial
#

So?

nova sparrow
#

Then I want to be able to modify arguments

fossil sundial
#

I don’t see an issue

#

Translatable components are translatable components

steady trellis
#

oh wait yeah, matt, why do you serialize to legacy then deserialize from legacy

nova sparrow
#

Would it be better to apply arguments before applying RGB

nova sparrow
fossil sundial
#

There’s a translatable component builder

#

But otherwise Component.translatable(key).color(…)

#

keys must not contain anything but themselves

#

Otherwise they’re not translatable

#

like “multiplayer.disconnect.outdated_client”

#

That is a translatable key

nova sparrow
#

Yeah I understand that

fossil sundial
#

And that key must only be that key.

#

If you look at the json this translates to:
You’ll always have the formatting outside the translatable section

fossil sundial
nova sparrow
#

With a regular message you'd do something like this

    public static Component format(String message) {
        return serializer.deserialize(message);
    }```
#

Would apply formatting and whatnot

fossil sundial
#

so?

#

That’s legacy

nova sparrow
#
    public static TranslatableComponent translatable(String key) {
        return Component.translatable(key); // apply formatting here 
    }```
fossil sundial
#

Otherwise the message must be a json

nova sparrow
#

So is it not possible to apply the formatting and still return that as a TranslatableComponent?

rich hawk
#

sorry for ping

fossil sundial
#

It is if you apply the formatting to an existing component …..

#

Components make up compounds

#

They’re json elements

#

You have to understand that calling .color(…) wraps the translatable component in another component

#

Which is why what you’re doing won’t ever work

nova sparrow
#

All I needed to know is that it wouldnt work tbh

#

I was getting that feeling

fossil sundial
#

Translatable components themselves cannot be styled but if you wrap components around them like with .color(…) then that will work

tawdry sky
#

Can you send players interactive books from velocity using adventure?

#

or is that like not implemented

#

Would be useful for GDPR shit

valid gazelle
#

Probably not, but if its possible the most you could do is just open.the ui, not actually give them a book in inventory

#

regardless its probably best with a plugin on back end server and maybe some syncing between them and proxy

#

Idk if there's any implementation on the proxy rn though

tawdry sky
#

just your classic "You can steal my data" prompt

fossil sundial
#

That said

#

I may make a plugin someday in the future that will allow usage of these features

#

(Requires a plugin downstream to work obviously)

burnt dragon
#

i mean, would be easy if it's a "on first join" thing

#

no need to worry about putting an item back, if that makes sense

#

all you'd do then is construct the packets and send them over

potent thunder
#

How can i get the plugin config?

#

Or do i need to implement it by myself?

fossil sundial
#

Velocity bundles sponge configurate 3

tawdry sky
#

I've got a very weird bug on my hands

#

With my /lobby command thingy

#

For some reason, it only works on either the lobby servers or "ob-main"

#

I'm probably blind, but I don't see what could be wrong

#

if done on other servers nothing happens

#
package lendmark.net.commands;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import lendmark.net.Main;
import lendmark.net.utils.Utils;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;

import java.util.Optional;
import java.util.Random;

public class lobby implements SimpleCommand {
    ProxyServer server;
    public lobby(ProxyServer server) {
        this.server = server;
    }

    @Override
    public void execute(Invocation invocation) {
        CommandSource commandSource = invocation.source();
        Player player = (Player)commandSource;

        RegisteredServer server1 = server.getServer("lb01").get();
        RegisteredServer server2 = server.getServer("lb02").get();

        if (server1.getPlayersConnected().size() > server2.getPlayersConnected().size())
            Utils.sendPlayerToServer(server2, player);
        else if (server1.getPlayersConnected().size() < server2.getPlayersConnected().size())
            Utils.sendPlayerToServer(server1, player);
    }
}```
#

the only other things that could be interfering with it are the ServerPreConnectEvent and the ServerPreConnectEvent

#

ServerPreConnectEvent

    @Subscribe
    public void ServerPreConnectEvent(ServerPreConnectEvent event) {
        Player player = event.getPlayer();

        if(player.getCurrentServer().isPresent()) {
            if (player.getCurrentServer().get().getServerInfo().getName().equals("ob-main") && !event.getOriginalServer().getServerInfo().getName().equals("ob-main")) {
                player.sendMessage(Component.text("§eUnloadujem pack.."));
                player.sendResourcePack("https://lendmark.blob.core.windows.net/lendmark/default.zip");
            }

            if (player.getCurrentServer().get().getServerInfo().getName().equals("auth")) {
                RegisteredServer server1 = server.getServer("lb01").get();
                RegisteredServer server2 = server.getServer("lb02").get();

                if (server1.getPlayersConnected().size() > server2.getPlayersConnected().size())
                    Utils.sendPlayerToServer(server2, player);
                else if (server1.getPlayersConnected().size() < server2.getPlayersConnected().size())
                    Utils.sendPlayerToServer(server1, player);
            }
        }
}
#

ServerPostConnectEvent

    @Subscribe
    public void ServerPostConnectEvent(ServerPostConnectEvent event) {
        Player player = event.getPlayer();

        ByteArrayDataOutput out = ByteStreams.newDataOutput();
        out.writeUTF("PlayerVersionChannel");
        out.writeUTF(player.getCurrentServer().get().getServerInfo().getName());
        out.writeInt(Via.getAPI().getPlayerVersion(player));
        out.writeInt(server.getPlayerCount());

        player.getCurrentServer().get().sendPluginMessage( MinecraftChannelIdentifier.from("lm:playerversionchannel"), out.toByteArray());
    }
}
fossil sundial
#

Don’t send a resource pack in pre connect. The client will always decline a resource pack while it can’t display the prompt

tawdry sky
#

So they don't have the different UI elements ext. for no reason

fossil sundial
#

You’re rebalancing twice

tawdry sky
fossil sundial
#

You call sendplayertoserver in the pre connect too

#

Why

#

You already have a connection in flight

tawdry sky
#

..is there a better way to do that?

fossil sundial
#

The event won’t be called if the player is not under way to be connected to a new server

#

Why are you trying to shoot yourself in the foot

tawdry sky
#

Auth has the GDPR shit ext.

fossil sundial
#

That’s unsupported btw

tawdry sky
#

Would be kinda useless if the player got sent to another server which has logs before giving consent

fossil sundial
#

every time I see auth I have to figure it’s a standin for a piracy plugin

tawdry sky
#

If they have consent all the server does it send them on their way

fossil sundial
#

That’s fine then

#

I’m not sure I follow your flow then

#

But don’t send a player elsewhere while you have a connection in flight

#

You’ll create a loop

#

Cause sending a connection to flight causes another connection to be in flight

#

See the issue?

tawdry sky
#

Yeah

#

I'll probably add something to cancel the old connection

#

But that still doesn't solve the issue why only the servers in the event do something with the hub command

fossil sundial
#

Now you lost me

tawdry sky
#

My issue is that when I do the /lobby command as seen above on lb01, lb02 or ob-main, it works

#

But if I do it on one of the other servers it doesn't do anything

#

Just seems to get canned

#

It's likely something incredibly dumb, but I'm blind

#

Something seems to be cancelling it, but I don't see the cause

#

See the issue?

#

anybody else

tawdry sky
#

sad

nova sparrow
#

@bold wharf I apologise for the ping but i think that yesterday you (or Five) mentioned about Velocity's debug mode? How can i enable that

bold wharf
#

I don't think that there is one bar specific packets

#

I may of said that I really needed to add one at some point

#

but, not aware of an existing one.

nova sparrow
#

Im still having an issue where i cant ping nor connect to my local server

bold wharf
#

(outside of the various system flag specific ones)

nova sparrow
#

Me and a friend both encountered this yesterday seemingly after a restart

#

No clue what could be causing it at all

#

Doesn't show in console when i attempt to ping the server and instantly shows the Disconnected screen when i attempt to connect

bold wharf
#

I mean, that gives very little for us to go off

nova sparrow
#

Well that's virtually all I have to go off myslef

#

I am struggling to even try debugging this

bold wharf
#

I mean, if you can do code stuff, ServerChannelInitializer

#

add a thing there to see if the channel bootstraps

#

but, I mean, adding logging for an issue we have 0 basis of is pretty "no go"

#

Shit like that is generally "incrementally flood the software with logger statements until you nail down where shit is going"

#

"Disconnected" is literally just the generic "we where told to fuck off"

nova sparrow
#

looks like its initializing a connection

lethal garnet
#

does velocity support sending sounds to an audience?

bronze yoke
#

no, sounds require a location and velocity doesn’t track that

lethal garnet
#

alright thanks

burnt dragon
#

(that's also not really why, it would need a registry which velocity would have to maintain for like all supported versions)

lethal garnet
#

i mean, you could just rely on the dev to enter a key?

#

and a location?

#

or am i missing something

burnt dragon
#

yes you are

#

sounds aren't all named

queen path
#

Hello, is there a way to get the players locale even before they connect to any server? or are in a world loading screen?

silver herald
#

hi, im trying to initialize a discord bot using JDA in the proxy initialize event, but i keep getting this error. can somebody help me out? im not too experienced with java

#

heres the code

sour current
#

JDA likely isn't being shaded, you need to setup shading in your build.gradle/pom.xml

silver herald
#

i see, are there any resources where i can learn more about that?

#

i dont know much about java

sour current
silver herald
#

thank you, ill check it out

old plover
#

hi guys

#

how to send title and subtitle

burnt dragon
old plover
#

I don't find anything

#

ty

willow bone
# craggy pecan Either set compression (optional) or login success (according to https://wiki.vg...

It's after login success, appears to be in the Forge handshake immediately after START is handled on both sides, the client is disconnected with SPacketDisconnect
Forge claims it receives an unregistered packet, Velocity disconnects the user.

Velocity:

[connected player] Player (/103.121.18.77:1142) has connected
[debug] Encoding packet SetCompression with id 3
[debug] Encoding packet ServerLoginSuccess with id 2
[debug] Encoding packet Handshake with id 0
[debug] Encoding packet ServerLogin with id 0
[server connection] Player -> forge has connected
[server connection] Player -> forge has disconnected
[connected player] Player (/<snip>:1142): unable to connect to server forge
com.velocitypowered.proxy.util.except.QuietRuntimeException: The connection to the remote server was unexpectedly closed.
This is usually because the remote server does not have BungeeCord IP forwarding correctly enabled.
See https://velocitypowered.com/wiki/users/forwarding/ for instructions on how to configure player info forwarding correctly.
[debug] Encoding packet Disconnect with id 26

Forge:

[Server thread/TRACE] [FML]: Handshake channel activating
[Server thread/DEBUG] [FML]: FMLHandshakeServerState: null->FMLHandshakeServerState$1:START
[Server thread/DEBUG] [FML]:   Next: HELLO
[Server thread/INFO] [net.minecraft.network.NetHandlerPlayServer]: S_Doppler lost connection: Internal Exception: io.netty.handler.codec.EncoderException: java.io.IOException: Can't serialize unregistered packet

Client:

[Netty Client IO #18/TRACE] [FML]: Handshake channel activating
[Netty Client IO #18/DEBUG] [FML]: FMLHandshakeClientState: null->FMLHandshakeClientState$1:START
[Netty Client IO #18/DEBUG] [FML]:   Next: HELLO
[Netty Client IO #18/INFO] [FML]: Unexpected packet during modded negotiation - assuming vanilla or keepalives : net.minecraft.network.play.server.SPacketDisconnect

I've since rebuilt forge with some extra debug logging, it looks like the START state completes on both ends, but the HELLO state never begins; my conclusion up to this point is Velocity is mishandling a retransmitted packet.

Why it only occurs only for new players on ~14% of first time connections https://i.cwlf.uk/dJNag, I have no clue, presumably something to do with overrideDim; but it doesn't occur if we remove Velocity from the stack.

old plover
burnt dragon
#

it does work

old plover
#

I can't view title

#

Component mainTitle = Component.text(traductColour("&5Sei sotto controllo anti-cheat!")); Component subtitle = Component.text(traductColour("&7Leggi la chat e non uscire!")); final Title title = Title.title(mainTitle, subtitle); target.showTitle(title);

fossil sundial
fossil sundial
agile ore
#

since it looks like you're mixing legacy and components, make sure to try it on a vanilla client, lunar is known to break stuff with components

#

(or just don't mix them)

fast canyon
#

do any of you guys know of a working** Global TAB player list for Velocity**? many weeks researching and testing velocity plugins for it without luck and mixed results, it just doesn't work, some kind of work, but when players leave or switch servers, the TAB doesnt update, I know TAB by Netz was perfect but, with all the drama is not supported for Velocity anymore, works but only on back end servers and NO global tab list 😦

nova sparrow
#

i’ve seen plenty of global ones work myself

fast canyon
#

example?

nova sparrow
#

old as hell

#

parts of the code may be relevant to replicate it to modern standards if necessary

fast canyon
#

no .jar

#

have to build it yourself

nova sparrow
#

yeah then build it yourself smh

fast canyon
#

I saw that one before, gonna give it a quick try, but I am pretty sure it will be the same result as the others, that are that old, when players switch servers ,the playerlist does not update

nova sparrow
#

Then add that yourself

#

i don’t think it’d be that hard really

#

maybe the sorting would be but like i said it’s done all the time

fast canyon
bold wharf
#

I mean

#

that's a stupidly old version of gradle

nova sparrow
#

Maybe it’s just best to make your own with similar logic and whatnot to the one i linked

magic forum
#

The limit is the Velocity's api. I can't do proper ping forwarding that FML2 understands with the api limitations

#

One thing I would like for the sake of showing FML2 medlist at ping is to allow plugins customize the Server ping more

#

I also got bstat working and my plugin is already running on a network

#

Right now I want as many people as possible to test and report to me if they find any issues or want to request a feature. I'm open.

fossil sundial
#

After my exam period I’m open to suggestions with the api for server pings

#

But not before

magic forum
#

Ok. Understanding

#

I just found out that the recent pixelmon mod ships with intergrated forge client reset packet mod

#

So I will try to integrate with that so people that has the mod can use it.

#

To be clear it's optional to have the client side mod

#

But if the mod is already there, why wouldn't it use it

twin ingot
#

Hi, after velocity update to latest version for support 1.19, I have issue with messages he is showing in the actionbar not in the chat.

bronze yoke
#

update viaversion to the latest dev build

twin ingot
#

Thank you ❤️

modest socket
#

I've been trying to create a Velocity plugin for about 2 days but only get the error The plugin file Nerf in Minecraft Proxy.jar appears to be a Bukkit or BungeeCord plugin.. Here is the code. I usually build with Intelij Artifact. Hope someone can help me

Main.java

package net.nim.proxy;

import com.google.inject.Inject;
import com.velocitypowered.api.command.CommandManager;
import com.velocitypowered.api.command.CommandMeta;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import net.nim.proxy.commands.TestCommand;

import java.util.logging.Logger;

@Plugin(id = "NIM-Proxy", name = "Nerf in Minecraft Proxy", version = "1.0", description = "Proxy Plugin", authors = {"Jonah Schmidt"})
public class Main {
    final ProxyServer proxyServer;
    final Logger logger;

    @Inject
    public Main(ProxyServer proxyServer, Logger logger) {
        this.proxyServer = proxyServer;
        this.logger = logger;

        logger.info("Nerf in Minecraft Proxy Plugin Loaded!");
    }

    @Subscribe
    public void onProxyInitialization(ProxyInitializeEvent event) {
        CommandManager commandManager = proxyServer.getCommandManager();
        CommandMeta commandMeta = commandManager.metaBuilder("test").build();
        commandManager.register(commandMeta, new TestCommand());
    }
}

TestCommand.java

package net.nim.proxy.commands;

import com.velocitypowered.api.command.SimpleCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;

public class TestCommand implements SimpleCommand {

    @Override
    public void execute(Invocation invocation) {
        invocation.source().sendMessage(Component.text("Test!").color(NamedTextColor.AQUA));
    }
}
oblique haven
#

like a plugin.yml or smth

modest socket
#

no

oblique haven
#

weird

modest socket
#

oh wait

#

this ?

#

I deleted the file now I get the error Did not find a valid velocity-plugin.json

nova sparrow
#

plugin.yml shouldn't really effect anything

#

and ive never seen a velocity-plugin.json in a velocity plugin

modest socket
#

Before I deleted the plugin.yml I got the error The plugin file Nerf in Minecraft Proxy.jar appears to be a Bukkit or BungeeCord plugin. The error is now

sour current
oblique haven
#

what's your build tool 0,o ant script?

sour current
#

they mentioned they're using the intellij artifact thing

oblique haven
#

hm, well you need to run the velocity annotations processor

modest socket
#

I don't use Maven or Gradle. Tried it at the beginning but couldn't manage to create a project with it

burnt dragon
#

well unless you think you're up for writing your own annotation processor i think now is a good time to learn

modest socket
#

okay

sour current
#

If you download the minecraft development intellij plugin it'll setup the project for you when creating it

modest socket
#

Okay, I'll try, give me a moment, please

#

This right ?

sour current
#

Yes

modest socket
#

Okay, I have now set up a Velocity project and when I try to build it I get the error error: Invalid ID for plugin net.nim.proxy.Main. IDs must start alphabetically, have alphanumeric characters, and can contain dashes or underscores.

burnt dragon
#

pretty clear error

#

your ID doesn't follow that

modest socket
#

am... I don't understand

bold wharf
#

I think it expects a lowercase name

modest socket
#

I have to lowercase this?

bold wharf
#

the id shouldn't have .'s inside of it

#

it's an id

modest socket
#

oh okay now i unterstand

#

Ah it works thank you very much

fickle grail
#

@fossil sundial
Hi, I want to make a pull request with a slight change inside ConnectionHandshakeEvent and I have two options.

  1. Pass the whole Handshake instance inside the event
  2. Pass unmodified Handshake#getServerAddress()

Which option do you prefer? or maybe there is a reason why this data is not passed to the event? or i should just make a fork for myself?

fossil sundial
weary moth
#

where & who do i give money

burnt dragon
#

me

weary moth
#

oh my god it's corey my second favourite person

oblique haven
#

❤️

bold wharf
#

I have an idea for a way to do it

#

I just have this whole like, thing where it feels like somebody ripped a layer of skin off my brain

#

I also kinda don't like it either

#

(but, idk a better way to do it)

fossil sundial
bold wharf
#

thoughts was on incoming, place in a queue

#

fire event

#

once event has fired, basically while (queue.peek.isComplete, senderion)

fossil sundial
#

Yes but the queue is also there to allow the proxy to fit messages in there it will send on its own

#

Remember commands are only partially signable

bold wharf
#

wait

#

they sing?!

oblique haven
fossil sundial
#

?

bold wharf
#

singable

fossil sundial
#

Oh

bold wharf
#

❤️

oblique haven
#

(quickly edits the post)

fossil sundial
#

Only the commands registered as chatlike through the chat registry

#

So do that first

#

We will need it to do this properly

#

Chat registry > Time disposition > Queue > Queue insertion

oblique haven
#

well we just have to use (essentially) what log4j uses to retain "order" internally, potentially some priority queue

fossil sundial
#

No priority. Signatures are absolute

bold wharf
#

doing the queue is trivial in a sense, insertion is a pita

#

but, you just need to order based on time

weary moth
#

how have you not have 5 million users complain about this issue on minehut @oblique haven

bold wharf
#

big caveat is popping said queue without just going back and making it blocking

oblique haven
#

not too many users on proxy->proxy where the issue sits (for us)

fossil sundial
#

This is a queue with side-channel

#

You need to be able to insert something sideways with believable time spacing

#

Or else the server will raise a stink about too quick messages

#

Which is why velocity also needs an incoming delimiter

#

This will be a magic waitForApproprtiateInsertion() loop internally

oblique haven
#

why are we not insertion sorting here

bold wharf
#

Issue with insertion sorting is, well, racy

fossil sundial
#

This will end up in a magic queue internally either way

oblique haven
#

any solution is going to have some kind of issue with high-latency systems

fossil sundial
#

Which is why I said store time disposition

oblique haven
#

I don't see a very easy way around that

fossil sundial
#

Time disposition also takes ping into account

bold wharf
#

only foolproof solution is to just remove the proxies interaction with this stuff

oblique haven
bold wharf
#

No

#

You work out the time difference between you and the client

#

so that when you go to add a thing to run, you don't end up fucking over the client

oblique haven
#

that'd be the delta, yeah

fossil sundial
#

A stupid offset rule

weary moth
#

what is bungeecord doing

oblique haven
oblique haven
fossil sundial
#

Removing it

bold wharf
#

yea, but nothing to do with flushing, it just's delta'd

weary moth
fossil sundial
#

Well

bold wharf
#

bungee removed support for sending that stuff to the server

#

they also just run pretty much everything on the network threads

oblique haven
fossil sundial
#

Bungee throws an IllegalArgumentException() if you call any send message or command function on the proxy with 1.19+

#

So they don’t care

oblique haven
#

clients care about ordered messages from other clients right?

fossil sundial
#

Yes but that’s an issue the server has to deal with

oblique haven
#

so we're assuming the packets coming from the server are ordered?

#

then this makes the whole thing a bit more sensible

fossil sundial
#

We don’t process server sent packets remember?

oblique haven
#

right

#

but we have to queue them in a way which makes sense to the client

#

if the proxy sends a message it has to mark it in the queue so we have to handle it at some capacity, which I assume is what the issue is for

bold wharf
#

We don't care about what comes from the server

#

we care about what we're passing to the server

oblique haven
#

so the server is the one caring about ordered-chat, not the client?

#

interesting, okei

fossil sundial
#

Velocity doesn’t support sending signed messages as chat to the client for now
That’s another project entirely

oblique haven
#

multi-proxy environments will suffer from this I think

fossil sundial
#

There’s an issue for it

oblique haven
#

right

fossil sundial
#

Let’s leave the church in town for now and focus on the order issue

#

Whatever you come up with here

#

I probably won’t like it
But in all fairness I can’t think of a good solution myself

#

random bullshit go

bold wharf
#

ez

#

move chat back to the network thread

#

runs

#

This is part of why I think a custom messaging channel for modern proxies might be an idea

oblique haven
#

well if chat order is really broken with the client, we should handle it accordingly, this doesn't seem all that intense

bold wharf
#

maybe something cleaner than bungees messaging channel if people have ideas of that mess

oblique haven
bold wharf
#

But, then we could add things like a command/chat channel and just pass the unsigned crap through and let the server determine what it wants to do with it

#

Not that that doesn't create issues of it's own, but, y'know

oblique haven
#

I don't think ordered chat -> server is going to be necessarily difficult, especially if we're trying to fulfill the player's personal chat queue

fossil sundial
#

I would be very happy if we could just add this to the velocity forwarding protocol: Ignore timestamp if timestamp is -6969 for example

#

But alas

#

That’s not a good option

oblique haven
#

I might take a crack at an implementation later tonight, I have a few ideas

bold wharf
#

I mean, I was just debating on that while using the pisser

#

It's far from ideal

#

But, I mean

#

it would solve so many other fucking issues

#

that would deal with the disposition mess at least afaik

#

then for chat, as I say, append future or whatever to a queue, fire event (which completes future on post), and after that, just have a task which drains the queue

#

only way I can see doing that without having some perma thread tryna deal with the queue

oblique haven
#

I don't think I'm understanding "out of order" chat, is there some writeup done on it? I know there was a write up done on signed messages specifically

bold wharf
#

messages have a timestamp on them

#

out of order means that it got a packet where the timestamp was earlier than the last packet we got

#

There is some caveats here that a badly timed clock sync, especially on modern hardware, can get them real good, but, we also pass stuff off into other threads for processing events, etc, which ofc makes a fair risk on our side

oblique haven
#

so the player -> proxy -> server channel is the only thing being checked against so somehow proxy -> server is becoming out-of-sync because the proxy is sending some packet like a command packet which makes the server believe the chat was out of sync?

#

is that what we're working with here

bold wharf
#

yes

oblique haven
#

okie doke

bold wharf
#

what am guessing here is that due to the magic of events firing, and maybe plugins, something somewhere is going sideways

oblique haven
#
@Subscribe
public void onChat(ChatEvent event) {
  // send command
  // result "accept" 
}
``` crude but potential reproduction of the bug yes?
#

hm interesting, okei

bold wharf
#

that's one way to do it, yes

#

having a hardcoded "ignore me" thing is a good idea, tbqh

#

Like, we're not able to send signed packets over to the server anyways

oblique haven
#

we could have paper hardcode timestamps of -1 as ignored

bold wharf
#

Only if in forwarding mode

oblique haven
#

only if velocity-support is enabled yeh

bold wharf
#

I also wanna add some leeway to that mess

oblique haven
#

managed "order" of velocity should happen when client talks to velocity, so paper should abandon the desire to validate unsigned messages in this circumstance

#

unless there's some reason we want unsigned stuff to be ordered - if we force signed objects to be ordered and drop unsigned objects as "unordered" or "ignored" we can just skip this whole issue because we can guarantee on the velocity side that it won't be passing down "unsigned" values unless it's explicitly allowed, and unsigned commands should be blocked at the proxy level as well if such a case exists where we don't want to be passing it, along with unsigned "chat" at the server level

#

intents may change this but if you drop the command intent then the validation should be passed to the server which should probably be denoted in the forwarding, but I think that's the "sane" way to handle this without adding magic values everywhere

bold wharf
#

how do you "force" signed objects to be ordered is the issue

oblique haven
#

future.whenComplete(() => <hook>) then it runs down to the next future and runs the same, adding hooks to futures even in post-completion works as expected as far as I understand

bold wharf
#

message 1 is sent

oblique haven
#

if there's no future handler it will just hold the value and stall (or should)

bold wharf
#

message 2 is sent

#

event handler for message 2 fin

#

event handler for message 1 fin

#

wat do?

oblique haven
#

future.whenComplete(() => <hook>) then it runs down to the next future and runs the same, adding hooks to futures even in post-completion works as expected as far as I understand

#

BasicQueue<CompletableFuture<SomeOrderedEvent>> queue;

while(true)
  next = pop queue; // concurrent "await" here for the next event in line
  next.whenComplete() // fire downstream packet
``` messages `client -> proxy` should exist in-order so when filling the queue we can "guarantee" this
#

when a Future lacks a handler it should just stall and calling whenComplete on a completed Future will just fire immediately

bold wharf
#

I mean, my theory was to basically generate the future into the queue

#

and then use the whenComplete to pop said queue

oblique haven
#

I liked your idea, yeah, it's sensible

bold wharf
#

I don't get where the while(true) comes into your thing

oblique haven
#

just jotted down

#

implementation wouldn't work exactly like that

#

whenComplete would need to call back to the queue to "free"

#

we can just use synchronized object locks for that though

bold wharf
#

basically, my thinking was that we didn't need to care in many respects

oblique haven
#
while true:
  cache.wait();
  next = cache.pop();
  next.whenComplete(() => cache.notify())
``` something like this makes some sense
bold wharf
#

in example of event 2 finishing before 1, the whenComplete would run, peek, and see that the first one isn't completed, and just disappear

oblique haven
#

there's some cache locking methods needed to sync it up but meh

oblique haven
bold wharf
#

No need for it to stall

oblique haven
#

it wouldn't logically stall the cpu - it just would be resolved and be waiting to be popped

#

completable futures aren't lazy (at least from what I understand)

bold wharf
#

I'm lost on what you're thinking then

oblique haven
#

okay hold on

#
// FutureCallable = CompletableFuture<SomeChatHandleOrWhatnot>

private final Stack<FutureCallable> futures = new Stack<>();

public synchronized void emitChat(FutureCallable callable) {
  futures.push(callable);
}

public void popChatQueue() {
  var nextFuture = futures.poll();
  nextFuture.whenComplete(item -> {
    playerChannel.emitChat(item.someChatValueOrWhatnot());
    popChatQueue();
  });
}
#

basic writeup of my thoughts, which I think is what you were thinking

#

this Stack is FIFO

#

not FILO (even though I think java's impl is)

#

this would require a "dedicated thread" but could be pushed into an executor queue which wouldn't be super bad, then we can just "re-queue" the poll task in the executor if we want

#

then we can do a stack.pop().isComplete() check to see if we can dump more from the queue

bold wharf
#

Yea, I didn't want a deadicated thread was my thing

#

I mean, dedicated thread works but my concern was is that we'd ideally want a per-connection queue, not per player

oblique haven
#

we can run this through executors and make the task re-assign itself so it self-propagates over as many threads as necessary

#

we don't need to do this in a single thread layout

bold wharf
#

and thus having a thread manage that just made it seem annoying, and having thread pools for just popping a queue gets tedious and inefficent

oblique haven
#

having a dedicated thread brings more issues at scale

#

having some pool run through the client queues seems more sensible at scale since it can scale easier

#

and it's not like the executor will always have a "wait", we can pop an entire queue, channel the entire queue, and not re-prop if the queue is empty

#

and if there's minimal chat mangling this should work very in-line, executors polling the queue doesn't seem like a bad thing here

#

I don't see a much better way to even put this together other than synchronizing the output into some "pre-channel" buffer

bold wharf
#

my thoughts was,
fun onChat(Chat) {
val chatFut = ComputFut.doStuff(fireEvent, etc, etc)
stack.push(chatFut)
chatFut.whenComplete( stack.peek().isComplete ( pop until queue empty or !isComplete))

#

I mean, thats messy, and, kinda bleh, but, I mean, I don't really see a none bleh solution here

#

lets us use the existing threads already in play to just do the trivial work of popping the queue

oblique haven
#

why don't we use a "chain"

#
Future somePlayerCachedChatFuture = CompletableFuture.completed();

onChat(Chat) {
  somePlayerCachedChatFuture = somePlayerCachedChatFeature.thenCompose(() -> /* new completable future */.whenComplete(/* flush packet */))
}
#

this would work no?

#

or rather wrapping the whenComplete on the outer layer

bold wharf
#

well, yes, but I wasn't aware on the thread safety inclinations of that

oblique haven
#

we can just lock the future

#

if it's all coming through the netty threads it should all be in-line

bold wharf
#

Well, the issue is the plugins

#

but, idk how we'd deal with that sanely anyways unless we just do the magic timestamp thing anyways

oblique haven
#

plugins can't sign so if we assume unsigned messages or commands are ignored for timestamps then this solves itself

#

which puts the "validation required" at the proxy level which is fine since we already der commands and messages

#

so if we Object.lock() the future then Object.wait() and Object.notify() make this super trivial for synchronizing future modifications

#

we'd probably use class level sync locks, or just some new Object() in a queue wrapper or something

#

lemme write up a quick POC

bold wharf
#

I mean, I see the concept, I didn't exactly wanna enforce 1 event at a time per player, etc

oblique haven
#

this is what I was thinking ^

bold wharf
#

that emit method looks sus

#

but, my brain is out of juice

#

like, submitting already completed futures to there already looks like a moot test case

oblique haven
#

Still need to figure out why 1 call is being omitted lol

oblique haven
#

unsure how this comes in to play with netty channels - but it seems to suggest that so long as the client is in-order it should process them sequentially

#

this is a rough mock up though - but it doesn't require a "dedicated thread" and allows for simple completable futures to chain off one another with a base "empty"

#
  private CompletableFuture<T> uniWhenCompleteStage(Executor e, BiConsumer<? super T, ? super Throwable> f) {
    if (f == null) {
      throw new NullPointerException();
    } else {
      CompletableFuture<T> d = this.newIncompleteFuture();
      Object r;
      if ((r = this.result) == null) {
        this.unipush(new UniWhenComplete(e, d, this, f));
      } else if (e == null) {
        d.uniWhenComplete(r, f, (UniWhenComplete)null);
      } else {
        try {
          e.execute(new UniWhenComplete((Executor)null, d, this, f));
        } catch (Throwable var6) {
          d.result = encodeThrowable(var6);
        }
      }

      return d;
    }
  }``` this kind of lets us play with it like that because it waits for the stage to be complete
#

and hinging synchronization on an object lock makes the most sense in java since iirc object likes are FIFO so acquiring the lock will put you in a read queue for the object which frees up after the sync block in emit

#
    public void emit(CompletableFuture<Chat> chatFutureLocal) {
        System.out.println("AI incr: " + MESSAGE_COUNT.incrementAndGet());
        synchronized (lock) {
            this.chatFuture.thenRun(() -> // after the current call finishes, whether it be now or later
                chatFutureLocal.whenComplete(BasicChatQueue::emitChatDemo)); // setup a hook for this call (which could be now or later) to emit chat when complete
            this.chatFuture = chatFutureLocal; // set the `chat future` to the local one to create the "chain"
        }
    }``` it's all very simple imo, but it should do the job for timestamp consistency unless the player is sending out-of-order packets which is _always_ an issue according to paper
#

I don't see how this breaks - we just can't push in our own proxy-owned information, so if we find a way to get paper to drop certain packets or "not care" about order for certain packets we can easily achieve the expected outcome through this ^ and all it does is back its way into the netty threads which initially controlled them

#

I don't exactly know how this will jump threads - but it should event 1 thread 1 emit message 1 <handle message 1 whenComplete in thread 1, thenRun in thread 2> event 2 thread 2 emit message 2 <handle message 2 whenComplete in thread 2, thenRun in thread n...>

#

this should be fine since the latest will dequeue on complete so we should have to worry about "artifact" values other than potentially the size of a chat packet which exists to push the chain along

#

and each player gets their own Queue since it uses a local lock object

#

(we can't use the chained future because it changes)

bold wharf
#

I mean, I can only see so much without it being in the actual impl which looks ass anyways

oblique haven
#

I mean the concept works in testing

bold wharf
#

I feel somewhat iffy on this, ngl; but, as said, there is no solution here which is gonna look great

#

The code in the proxy doesn't exactly look well designed for shoving this into is what I mean

#

I also don't know how/where you plan to hook it in and what the side effects of that will be

oblique haven
#

we put it in the BackendChannelPlay handler

#

then run it on handleChat and wrap the chat event in the future

#

then pass the future into the linked event inside of the backend play handler

#

we don't copy this 1-1 into velocity for sure - but the idea works which is what I'm grabbing at

bold wharf
#

my one thing is is that it looks like you can't have 2 events processing for a single player and that it's basically just gonna act like a glorified queue

oblique haven
#

if the 2 events are processing in 2 different threads you definitely can

bold wharf
#

I mean from a singular player

oblique haven
#

that's what I'm saying as well

#
    public static CompletableFuture<Chat> chatFuture(String message) {
        final Chat chat = new Chat(message, new Date());
        TO_CALL.add(chat);
        return CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(ThreadLocalRandom.current().nextLong(100, 200));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return chat;
        }, executor);
    }

    public static void main(String[] args) {
        BasicChatQueue queue = new BasicChatQueue();
        for (int i = 0; i < THREADS; i++) {
            final int e = i;
            var t = new Thread(() -> {
                try {
                    for (int t1 = 0; t1 < 3; t1++) {
                        Thread.sleep(ThreadLocalRandom.current().nextLong(5, 10));
                        queue.emit(chatFuture("Test Thread %d (%d)".formatted(e, t1)));
                    }
                } catch (InterruptedException exx) {
                    throw new RuntimeException(exx);
                }
                var x = THREAD_COUNT.decrementAndGet();
                System.out.printf("Teardown for thread %d%n", x);
                if (x == 0) {
                    BasicChatQueue.executor.shutdown();
                }
            });
            t.start();
        }
    }``` these test markings `5-10ms between calls` and `100-200ms` of latency within __every__ chat call finishes in about 1 second
#

if these weren't running in parallel it would take like 2 minutes or smth

#

the Thread.sleep(100 -> 200) imitates handling of the packet, and the 5-10 in the bottom accounts over some form of latency

bold wharf
#

yea, I mean, idk, am tired and can't really judge it on all I can see atm

oblique haven
#

no sweat, this does seem like it's working though with fairly minimal lift

#

the idea is essentially

cachedFuture = completed future of some sort;

emit(newFuture) { (synchronized call)
  cachedFuture (when finished) -> add chat handler to newFuture to emit packet
  cachedFuture = newFuture
}
``` saying anything more is vastly over-complicating the scenario
#

then we drop the cached future and it's left to die in the GC

#

these futures are immediately dropped once the next handler runs through so we're always cleaning up behind ourselves

#

that's enough text dumping for me for now though - let me know what you think in the morning 🙂

#

keep in mind this impl doesn't work unless we let the backend server get rid of certain packets which have magic timestamps or something similar since our packets cannot go through this queue, keeps in mind latency and everything like that since TCP is transactionally based and will (usually? if not always) come in the order it's sent from the client

bold wharf
#

also, do note that you need to handle command packets in there too

oblique haven
#

that's fine, the CompletableFuture it takes would be generalized enough to contain whatever

#

java doesn't make that part hard so we have an easy win there

#

we can just do like Either<X, Z> either.caseOfX(x -> {}) or whatever we want to do, there's so many options in modern java

craggy pecan
#

modern java... says Either...

#

We have records now

#

and sealed interfaces

oblique haven
#

or whatever we want to do
I'm aware of the modern java constructs

bold wharf
#

we're java 11

oblique haven
#

😉

craggy pecan
#

ugghh... I forgot about that

oblique haven
#

hopefully 18 soon constantsigh

bold wharf
#

jumping to latest LTS on next major is defo an idea

craggy pecan
#

Considering MC requires 17 and most (all?) users running a proxy run a server, what's holding the update to java 17?

bold wharf
#

I dont wanna be chasing releases, however

#

major release, bumping java version mid cycle is bleh

#

Theres much to do for mc 1.19, but, post 1.19, I wanna do a release

oblique haven
#

we should probably follow MC client version spec for Velocity

craggy pecan
#

eghh, Java is "technically" backwards compatible (for >9)

oblique haven
craggy pecan
#

how so?

oblique haven
#

well I guess not in runtime

#

hm

bold wharf
#

I mean, breaking everybodies environment mid cycle to tell them to update java is not nice

oblique haven
#

(well)

bold wharf
#

that's why I'd prefer to do it on a major, maaaaaybe a minor

#

but, defo not mid patch

oblique haven
#

makes sense

craggy pecan
oblique haven
#

java 12?

#

I've never seen that version used in my life

bold wharf
#

1

#

but, graph is irrelevant for this discussion

craggy pecan
#

sure, you're right, we shouldn't update until 1.19 is polished

bold wharf
#

as said, java bump would be ideally on a major, maaaybe on a minor

#

not my decision entirely, but, yea

oblique haven
#

I think the idea is to only push java on major MC version releases so that people don’t lose support for a version in the middle of a version @craggy pecan

bold wharf
#

I mean, we're not tied to mojang versioning

#

"official" policy for paper is the previous LTS iirc

oblique haven
#

Yeah but Velocity has built in stuff which handles backporting

#

I think that brings it to a different area even though paper itself doesn’t support legacy

#

Like I mean Via is just a hack - Velocity has built-in support (which is good) but Velocity usually does major revisions at the end of a version, or during the transition into a new version which seems like the most sane time to do such updates

#

Java 17 is LTS

analog cedar
#

I've seen that Velocity supports Brigadier, but I have not seen any signs of Minecraft related argument types being implemented. Are the Minecraft related argument types implemented by Velocity? For example, how do I make a command with an int range? (like 3..49, where 3 ≤ x ≤ 49) I understand that most of these will not make sense without more context on the server (like selectors), but registering these types of commands would make tab-completion much, much easier

sour current
analog cedar
#

i asked about the Minecraft specific argument types

opaque escarp
#

Velocity only has access to the default Brigadier argument types, although there is probably a way to get the Minecraft argument types or inject custom ones (e.g. https://github.com/PaperMC/Velocity/blob/dev/3.0.0/proxy/src/main/java/com/velocitypowered/proxy/command/brigadier/StringArrayArgumentType.java ), but I don't think it is supported or recommended

GitHub

The modern, next-generation Minecraft server proxy. - Velocity/StringArrayArgumentType.java at dev/3.0.0 · PaperMC/Velocity

fossil sundial
#

I don’t see a reason to provide the game types to api
You wouldn’t be able to use them correctly without the data from the server or client anyway
Plus they’re highly version dependent and iffy in conformity

signal ember
#

Was about to ask something similar, would there be any way to use a TextArgumentType? Obviously it uses a Text and not a Component, but is there any way it could be wrapped to provide the same output for the client as they type?

fossil sundial
#

I’m not following

signal ember
#

the tellraw command uses a TextArgumentType to parse a Component (well a Text in Mojang terms), and on the clientside it parses it to tell if it's valid as well (at least that's my understanding, unless I'm wrong and that has happened before)

#

Obviously I could re-implement this with GsonComponentSerializer, but then the client wouldn't have the same feedback

fossil sundial
#

Doesn’t that exist already? No clue

signal ember
#

Not from what I can tell?

#

Minecraft provides it as the parser minecraft:component, at least that's what I'm gathering from wiki.vg

#

Not sure how ArgumentType<T> provides what kind of type it parses? only ever looking into brigader and it's MC impl now

analog cedar
#

again, thats what i was asking for

analog cedar
#

not sure about them being version dependent, as these don't necessarily change

fossil sundial
analog cedar
#

Again, i'm not talking about those

#

for example, the raw text component has no ingame context whatsoever

nova sparrow
#

Five how can i send packets to a player without relying on a 3rd party api like protocolize?
Doesn't look like the Player interface allows you to send packets to a connection

fossil sundial
#

Isn’t intended. Go look at how ViaVersion injects

fossil sundial
#

That was meant as a reply^

analog cedar
#

thats why i was asking mainly

#

yeah no worries

#

Another question: if i use a BrigadierCommand for registering commands, will they work in some sort of legacy mode with older clients? (for example with ViaVersion)

fossil sundial
#

Yes

#

I’m not open for discussion on any of this till the 25th

#

I have exams starting tomorrow

signal ember
#

sure

nova sparrow
signal ember
#

i'll just implement an argument type and serializer for minecraft:component as Component and put the PR up

#

cause I feel as at least that one should exist for clients that support it

fossil sundial
#

Internally there is already

#

Just a dummy for now

signal ember
#

no, there isn't

#

it's empty

#

yeah okay

fossil sundial
#

It is empty though

signal ember
#

correct ^^

fossil sundial
#

The impl would also be a placeholder

signal ember
#

why would it?

#

GsonComponentSerializer?

fossil sundial
#

Cause the worst you could do is verify it

signal ember
#

huh?

#

what are you talking about

fossil sundial
#

Otherwise the processing is client side

#

Brigadier tells the client “component here”
And nothing else
What you want is to have the proxy do a placeholder swap
Which is not an argument decoder

#

a magic <T>

signal ember
#

I don't understand?

#

I want to be able to have specify a Component as an argument in my plugin

#

so the client knows it's there

#

and that's currently not possible

analog cedar
#

so like

#

what if you want to create a /tellraw command but on the proxy

#

you can message players components already, and you could get a component from the argument directly

signal ember
#

Alright, implemented it... will fix it up and throw a PR for anyone that wants to look at it

charred pulsar
#

does velocity have a yaml implementation included?

opaque escarp
charred pulsar
charred pulsar
#

i wonder does velocity have way to execute "commands" from code? searching those dispatchCommand, invokeCommand terms on javadocs does not seems to be a thing

bold wharf
#

on the command manager thing

#

it's like runAsync or something

lethal garnet
#

i remember this being on the velocity forums somewhere

ashen fiber
#

I wouldn't use the configurate version provided by Velocity, it's a major version behind.

undone jackal
#

hey! is it possible to write a plugin for velocity that can add additional servers to the network? I'm trying to scale my minigame servers w/ docker but I cant find a way to add a new server to velocity.

bold wharf
#

yes, there is a method to create a registered server somewhere and register it into the proxy

undone jackal
#

epic thanks!!

slow thistle
#

how do you do async stuff

charred pulsar
vestal prawn
#

or create your own scheduler

quiet kestrel
#

Is there a possibility to use Yaml instead of Toml for configurations?

nova sparrow
#

Believe velocity has it built in

winged pike
#

how could i store info inside blocks previous to 1.16?

nova sparrow
#

probably not the right channel

old plover
#

Hello, I don't find a method for broadcast at player with custom perms a message

#

anyone can help me?

burnt dragon
#

iterate/filter