#velocity-dev

164 messages · Page 13 of 1

old plover
#

anyone can help me with implementing cooldown?

oblique haven
#

that's a pretty normal system which should have a good amount of stuff on it - but it also takes time to write so people probably won't walk you through it manually

old plover
#

I find a method but it's not working

oblique haven
#

well what's not working about it - can you give us more info, maybe some stuff you've tried

#

we can probably point you in the right direction

old plover
#

okay

#

wait

#

public HashMap<String, Long> cooldowns;

nova sparrow
#
public class Cooldown {
  private final HashMap<Player, Long> cooldowns = new Hashmap<>();

  private void add(Player p, long timeInMillis) {
    coldowns.put(p, System.currentMillis() + timeInMillis);
  }

  private boolean isOnCooldown(Player p) {
    return cooldowns.get(p) != null && cooldowns.get(p) <= System.currentMillis();
  }
}
#

Idea shrug

#

globalised cooldown thing

old plover
#

@Override
public void execute(Invocation invocation) {
this.cooldowns = new HashMap<String, Long>();

nova sparrow
#

dont expect it to just work

#

wait

old plover
#

if (this.cooldowns.containsKey(executor.getUsername())) {
long secondsLeft = this.cooldowns.get(executor.getUsername()) / 1000L + COOLDOWN_TIMER - System.currentTimeMillis() / 1000L;
if (secondsLeft > 0L) {
executor.sendMessage(Component.text(traductColour(String.valueOf(secondsLeft)).toString()));
return;
}
}

old plover
#

ok I have fixxed

#

thank you to all

burnt dragon
#

genuinely terrible idea

#

and something you could do yourself if you wanted to do the terrible idea

#

in what universe is caching authentication a good idea

#

that... is not.. ok

#

whatever

#

"house" do you know anything about shared ips

#

vpns are not the only thing that use shared ips

#

you'd block schools, flats, dorms, most isps

#

ok what about the three other things i mentioned

half locust
#

an entire ISP could have thousands of randos sharing the same public IP

burnt dragon
#

ah yes "security through hoping people don't know other people"

half locust
#

otherwise known as "let's hope people don't bruteforce usernames"?

#

I'm sorry but having a subdomain with alphabet soup is not a captcha

charred pulsar
#

can somehow i put maven version inside a velocity plugin?

#

since the Version is put inside the soruce files than resources

magic forum
#

Is there any reason why velocity's stable version is 3.1.1?

#

It doesn't support 1.18.2

bold wharf
#

because people got busy and theres still pending stuff to do before we can release .2

slow thistle
#
[19:12:00 ERROR] [axovelocity]: Error occurred while attempting to connect to Database.
[19:12:00 ERROR]: java.sql.SQLException: No suitable driver found for jdbc:mysql://ip:port/database?useSSL=false
[19:12:00 ERROR]:       at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:706)
[19:12:00 ERROR]:       at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:229)
[19:12:00 ERROR]:       at net.axolotlhub.axovelocity.sql.MySQL.connect(MySQL.java:22)
[19:12:00 ERROR]:       at net.axolotlhub.axovelocity.Main.onProxyInitialization(Main.java:69)
[19:12:00 ERROR]:       at net.axolotlhub.axovelocity.Lmbda$1.execute(Unknown Source)
[19:12:00 ERROR]:       at com.velocitypowered.proxy.event.UntargetedEventHandler$VoidHandler.lambda$buildHandler$0(UntargetedEventHandler.java:47)
[19:12:00 ERROR]:       at com.velocitypowered.proxy.event.VelocityEventManager.fire(VelocityEventManager.java:598)
[19:12:00 ERROR]:       at com.velocitypowered.proxy.event.VelocityEventManager.lambda$fire$5(VelocityEventManager.java:479)
[19:12:00 ERROR]:       at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[19:12:00 ERROR]:       at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[19:12:00 ERROR]:       at java.base/java.lang.Thread.run(Thread.java:833)

I'm trying to hook up my velocity plugin to a MySQL database, anyone know how I can fix this?

robust mural
#

Compile you driver with your build tool

slow thistle
#

So a shaded jar?

robust mural
#

Yes

slow thistle
#

Already doing that

wary tiger
# charred pulsar since the Version is put inside the soruce files than resources

Yes, you can. You would use the templating-maven-plugin as follows:

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>templating-maven-plugin</artifactId>
                <version>1.0.0</version>
                <executions>
                    <execution>
                        <id>add-plugin-info</id>
                        <goals>
                            <goal>filter-sources</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

Then create a class in src/main/java-templates and define a public static final String VERSION = "${project.version}"; constant inside it. You may then reference this constant in your @Plugin annotation.

#

The templating-maven-plugin, it may be evident, will filter source files inside src/main/java-templates.

wary tiger
#

If you decide to use HikariCP, then I recommend using the data source instead of the driver.

#

Please ping me profligately if you have further questions.

slow thistle
wary tiger
#

Yes. (Relocation will handle changing the classname string)

slow thistle
#

Alright, I'll give it a try

slow thistle
wary tiger
#

Look inside your plugin jar - open it up with an archive tool. Make sure the MySQL driver classes are present.

slow thistle
wary tiger
#

The classes you will be shading begin with com.mysql, not java.sql

slow thistle
wary tiger
#

My bad, assuming you relocated correctly, the driver class will be in the relocated folder. For example, com.yourpackage.libs.mysql

slow thistle
#

No such folder exists

charred pulsar
#

I went with stupid approach that just make velocity-plugin.json manually

median kraken
#

How can information be exchanged between the proxy and the server?

#

For example, the player did something on the server and I want to transfer this information to the proxy

fossil sundial
oblique bay
rough tangle
#

java.lang.RuntimeException: Unable to create instance of interface net.kyori.adventure.text.Component. Registering an InstanceCreator or a TypeAdapter for this type, or adding a no-args constructor may fix this problem.
Trying to package a Component in to GSON causes this error. Is there a build in class or should I create a TypeAdapter?

burnt dragon
#

GsonComponentSerializer

rough tangle
#

Map<String, String> eventWrappingData = (Map<String, String>) GSON.fromJson(payload, Map.class);

burnt dragon
#

there's a populator method that you can use on your gson builder

#

so like

var myBuilder = whatever;
myBuilder = GsonComponentSerializer.gson().populator.apply(myBuilder)
rough tangle
#

Thanks that is working, there doesn't happen to be a serializer for sound? It not erroring but it doesnt seem to be playing it. I am checking the data now

#

It looks like trying to convert sound results in it being null

rough tangle
#

Also I could've sworn paper natively supported adventure-platform. However looking through my maven packages I don't see that. Do I need to include it separately now?

burnt dragon
#

There is no sound serializer no, hence why it's called ComponentSerializer

#

Paper does not and has never included adventure-platform - it natively implements the api, so things like Player implement Audience, thus making adventure-platform useless

rough tangle
burnt dragon
#

why do you have the spigot jar in your classpath if you are using paper

#

and no, you'll have to make your own serialiser

rough tangle
#

for the remapped jar

#

I am currently unaware of a way to easily get the remapped jars without compiling paper. If there is something dumb I am missing I would love to know about it.

burnt dragon
#

you are yes

atomic leafBOT
burnt dragon
lunar quail
#

are there any use cases differences between redis pubsub, rabbitmq and grpc for broadcasting database updates across minecraft server network running behind velocity (there may be multiple velocity proxies with the same set of backend servers)?

#

updates like

  • party members list change
  • game state changed (e.g. game started ⇒ should no longer send new players to this server)
    etc.
rough tangle
#

@true chasm One last thing if you look into the repo again, in the velocity package, I am getting an unresolved reference @ compile("com.velocitypowered:velocity-api:3.1.1")

true chasm
#

you probably want compileOnly

inner surge
#

how can I serialize a component and then deserialize (im using velocity)

atomic leafBOT
inner surge
#

Also

#

Whats the best way to catch the players that get kicked

#

when the proxy shutdowns

#

I'm runing multi proxy and i have to fix the player count, .getAllPlayers returns empty on proxy shutdown

#

shouldnt the DisconnectEvent get called

burnt dragon
#

there's a kicked event

#

but disconnect event is a bit temperamental iirc

crystal cliff
#

Hello, I'm new on Velocity and I have two questions about plugin development:

  1. Velocity provides folder name in lower case for some reason when i use @DataDirectory injection (platform standard?).
  2. When I using logger provided by velocity injection log records from my plugin looks like this:
    [01:06:01 INFO] [com.feniksovich.x.y.z.w]: <MESSAGE>
    Instead of:
    [01:06:01 INFO] [PluginName]: <MESSAGE>

Any ideas about #1 and fixes for #2?
Thanks in advance.

undone jackal
#

Is there a method to send change the player's currently connected server?

#

nvm i found it (createConnectionRequest)

pearl harness
#

I'm confused on how the async events work. For example, I've got a PlayerChooseInitialServerEvent and I want to modify the initial server but I have to do some async processing in order to determine what I want to set the initial server to. Is it as simple as this for example?

    @Subscribe(order = PostOrder.EARLY)
    public void onInitialConnect(PlayerChooseInitialServerEvent event, Continuation continuation) {
        someFuture.thenAccept(targetServer-> {
            event.setInitialServer(targetServer);
            continuation.resume();
        });
    }```
burnt dragon
pearl harness
#

I understand the continuation is a callback to resume event execution but I'm not clear on what I can call and where

fossil sundial
#

Discord please

pearl harness
#

lmao

#

Alright what would be they way to do what I described? Or is there no way currently?

fossil sundial
#

just run whatever you need to do and then set the result

#

Just make sure it doesn’t take longer than 3 sec

pearl harness
#

😄

fossil sundial
#

That’s not a velocity limit

#

It’s a client limit

pearl harness
#

Gotcha

#

And if it does take longer than 3 seconds?

fossil sundial
#

The client can get disconnected with a timed out message

pearl harness
#

can or will?

fossil sundial
#

Anything up to 3 sec is safe

#

Anything above isn’t

pearl harness
#

gotcha

#

Alright I'll put a timeout on my futures for 2.5 seconds

fossil sundial
#

We don’t know to be exact. Modded clients allow a much longer wait time

pearl harness
#

and just not connect them if it takes longer

#

Thanks though!

#

@fossil sundial But can I still run that continuation stuff though?

#
    @Subscribe(order = PostOrder.EARLY)
    public void onInitialConnect(PlayerChooseInitialServerEvent event, Continuation continuation) {
        someFuture.thenAccept(targetServer-> {
            event.setInitialServer(targetServer);
            continuation.resume();
        });
    }``` Like I feel like this is valid or I'm still not understanding
#

since its async, the initial server it set async later when the future completes then event execution is resumed

#

Or does that continuation stuff only mean the next events are run once that continuation is complete

fossil sundial
pearl harness
#

oh I see

fossil sundial
#

That’s why I said if you need data you can’t be async

pearl harness
#

gotcha

#

So I think I'm still missing the reason for events being async

#
  @Subscribe(order = PostOrder.EARLY)
  public void onLogin(LoginEvent event, Continuation continuation) {
    doSomeAsyncProcessing().addListener(continuation::resume, continuation::resumeWithException);
  }```
Like this is from the docs, I dont really see the idea of it
pearl harness
pearl harness
#

got me wondering what the point of these async events are

bold wharf
#

Because either you're on the network thread or you're not

#

idea of async is so that you're not clocking the networking thread

quartz shadow
#

The wiki says. " The event system allows a plugin to pause sending an event to every listener, perform some unit of computation or I/O asynchronously, and then resume processing the event". Specifically the "then resume processing of the event" makes me feel like it will not process the event fully until the continuation is resumed

bold wharf
#

hm, am not really sure how the continuations work, tbqh

pearl harness
bold wharf
#

Looks like maybe you need to return the continuation?

#

For an annotation-based listener, all that is needed to process an event asynchronously is to either return an EventTask or add a second Continuation parameter

#

oh

#

hm

pearl harness
#

from the wiki the only one that requires returns is the eventtask

#

yeah :/

bold wharf
#

Like, the logic does look like it's supposed to do that

pearl harness
#

Anyone know who wrote it? 😄

bold wharf
#

was backported from the polymer branch

#

I don't see where that is even handled, however

pearl harness
#

yeah idk about u but I cant think of a reason to give the implementer a continuation to resume without letting them handle execution

#

If anyone knows the workings of these async events besides being processed on another thread please lmk, it'd be very helpful

keen vale
#

Hey, trying to modify this plugin a bit.
Over at line 113 on https://github.com/Erisfiregamer1/PistonQueue/blob/main/src/main/java/net/pistonmaster/pistonqueue/shared/PistonQueuePlugin.java the plugin checks if the server is online and if so set a var to true
How do I make it so it does that after a successful ping?

GitHub

Best queue plugin out there! Forked for Worlgik for specific changes. - PistonQueue/PistonQueuePlugin.java at main · Erisfiregamer1/PistonQueue

keen vale
#

Help?

bold wharf
#

I mean, we can't really do a deep-dive on the source for random plugins to give you an answer

#

iirc, there is a method on the server info thingy or maybe RegisteredServer to ping the server, ping it and see if you get a response

craggy pecan
# pearl harness If anyone knows the workings of these async events besides being processed on an...

If you need unconditional asynchronous execution for all events of a certain type, you can set the async attribute on the @Subscribe annotation (see https://github.com/PaperMC/Velocity/pull/384/files#diff-815fdc6d02e26aaee3fe4d2992d3765be1c0e456b05e5d5838aed15774882bf6R34). As electroniccat said, an event can have conditional asynchronous execution (e.g. migrate threads mid-execution) by returning an EventTask. In this case, the most useful impl is EventTask.WithContinuation. Then, the event manager will wait until you resume the continuation to call the remaining handlers (see https://github.com/PaperMC/Velocity/pull/384/files#diff-d8ddbbf479b18d6b2c4bebc809feb8fb37dd0f305c79bf84aed7e534091f1b0aR423 for details). Do note that the event task need not be async and it can block the Netty thread; I wouldn't recommend this unless the computation is trivial. A complete example (ignore the formatting, am on mobile):

@Subscribe
    EventTask onMyEvent(MyEvent event) {
      // Do something on Netty thread (probably, see technicality below)
      return EventTask.asyncWithContinuation(continuation -> {
        // Running on a separate thread pool, you can do expensive stuff here. This lambda is called by the event manager after the handler (the onMyEvent method) returns the EventTask containing it.
        // You can mutate the event here. The object is received by future handlers; thread-safety is guaranteed by the event manager.
        event.setProperty("bar");
        // Notify the event manager the asynchronous computation is complete. This is needed since e.g. we could create a new thread in this lambda and let it resume the continuation itself, without needing to join it.
        continuation.resume();
    });
}
GitHub

This implements the "Handling of potentially blocking events" portion of the event rework issue #378.
The implementation no longer uses the kyori event bus, but a custom implement...

bold wharf
#

The doc states that it can have the 2nd param as a Contination

#

but, I dont think that's even hooked in the current release

craggy pecan
#

For your case, however, using EventTask.async is simpler and cleaner; continuations are useful for more complex thread coordination. Thus, the code above is equivalent to

@Subscribe
    EventTask onMyEvent(MyEvent event) {
      // This *can* be run on the Netty thread.
      return EventTask.async(() -> /* This runs on a separate thread */ event.setProperty("bar"));
    }
craggy pecan
#

Technicality: a handler that's not marked async may be run on an async thread. This can occur e.g. to the remaining handlers after a handler returned an asynchronous event task.

wary tiger
#

If I may be permitted, allow me to explain the motivation behind all this:

The objective of asynchronous listeners is to improve efficiency by reducing thread jumps (called context switching). Before async listeners, here is what would happen:

  1. Velocity encounters some event
  2. The event manager fires the event on another thread
  3. Every listener performs its computations on this separate thread
    If Velocity needed the results of the event, it would then resume relevant operations after the completion of step #3. So, on the whole, Velocity fires an event, the listeners perform computations on a separate thread, then Velocity resumes relevant operations if applicable.

A context switch occurs between #1 and #2 when we switch threads. With async listeners we intend to reduce the preponderance of context switching. An async listener is rather a listener which has control over its own thread context. An async listener can request to always use another thread or it can always use the same thread; it can dynamically switch threads too, if it wishes.

Supposing all our listeners to be async listeners:

  1. Velocity encounters some event
  2. The event manager calls the first listener.
  3. When the EventTask from the first listener is complete, the event manager calls the second listener.
  4. When the EventTask from the second listener is complete, the event manager calls the third listener.
    ...
    Once all listeners are complete, Velocity resumes relevant operations. The use of EventTask delegates control over context switching to the async listener. (However, note that in the current implementation, one listener cannot determine the thread context of the next listener).
crystal cliff
#

Is ServerResourcePackSendEvent appeared in 3.1.2 version?

fossil sundial
crystal cliff
#

ty

crystal cliff
#

Is there a way to cancel (denied) ServerResourcePackSendEvent and not send DECLINED status to downstream server?

fossil sundial
crystal cliff
#

I'm trying to make plugin that prevents resource pack double-installation for the players already installed resource pack once.
It useful for servers where resource pack applies on backed server (downstream, in lobby server for example).

If a player switches server and then returns to the lobby again, they will have to wait for the resource pack installation process again, since the server/client doesn't check that such a resource pack is already installed.

fossil sundial
#

Otherwise we have to assume you’re actually updating the pack

#

Let me quickly see if that’s what we did

fossil sundial
crystal cliff
#

Okay, it would be really nice if this was implemented at the proxy server core level 👍

fossil sundial
#

@oblique haven if you wanna grab that free PR
In the backend play session handler
Check if the currently applied pack has the same hash and if yes return true and send a success downstream

fossil sundial
#

One thing to consider here

#

If there’s a pending pack how would we handle that

#

Don’t have the mental capacity for that atm

fossil sundial
#

That will also fix it

crystal cliff
#

Thank you Five for quickly support

crystal cliff
fossil sundial
crystal cliff
#

I don't quite understand why this would be a problem.

According to my implementation for BungeeCord, I simply store a map with UUID and resourcepack hash.
If the player's UUID wasn't there, I wait for the client to send a packet with the SUCCESSFULLY_LOADED status to add it to the map.
I wait for a packet from the server, which will send resource pack installation request to the player again. If the received and stored hashes match for this player, then I simply cancel it and send a packet to the downstream with the SUCCESSFULLY_LOADED status.

#

Maybe I'm missing something thinking_gun

fossil sundial
pearl harness
#
    @Subscribe(order = PostOrder.EARLY, async = true)
    public void onInitialConnect(PlayerChooseInitialServerEvent event) {
        EventTask.asyncWithContinuation((continuation) -> {
            someFuture.thenAccept(targetServer-> {
                event.setInitialServer(targetServer);
                continuation.resume();
            });
        })
    }```
craggy pecan
#

You can mutate the event; let's prove it: your event handler is called here https://github.com/PaperMC/Velocity/blob/e8bf6ab5222d8bbf4e59e7c4d5400b10ab4c7e81/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java#L598. Assume you return an EventTask. Then, the ContinuationTask below is executed, after receiving the event object. Also assume your plugin resumes the continuation. Then Velocity executes the next handler here https://github.com/PaperMC/Velocity/blob/e8bf6ab5222d8bbf4e59e7c4d5400b10ab4c7e81/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java#L583. Note that it is passed the same event object. When the last handler resumes its continuation, the future is completed with that event object https://github.com/PaperMC/Velocity/blob/e8bf6ab5222d8bbf4e59e7c4d5400b10ab4c7e81/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java#L577

GitHub

The modern, next-generation Minecraft server proxy. - Velocity/VelocityEventManager.java at e8bf6ab5222d8bbf4e59e7c4d5400b10ab4c7e81 · PaperMC/Velocity

pearl harness
#

Thanks this makes more sense now, not sure what Five was talkin about earlier

craggy pecan
#

No problem 😜

#

If anyone wants to add this/the previous message to the wiki, feel free. Too busy rn to do it myself

fossil sundial
#

It’s not async

#

And it can’t be because it’s linked or chained

pearl harness
#

huh

#

you sayin I can block for my futures in that event and just block whatever thread is running that event and potentially others?

pearl harness
vale wharf
#

Is there anything in the api that allows me to grab the players on a specific server ?

#

The amount of players

bold wharf
#

in a singular instance, you'd basically just check get the players which are on that registered server

vale wharf
#

So for instance a "hub" plugin with the selector, I'd want to get the players on {minigames}.

oblique bay
#

If it's an unknown server name I'd do what electronic said, probably loop through all players online or just keep that info stored and ++ -- when someone joins/leaves

hybrid gorge
#

Is t possible to set the uuid of a player? On bungee you do it with the PreLogin event

hybrid gorge
#

I cant find anything there

#

thats why i ask

#

im not as dumb as other people that dont know java docs

#

otherwise i wouldnt ask here

oblique bay
hybrid gorge
#

my question is

#

Is it possible to set the uuid of a player

tawdry sky
#

Does Velocity support dem fancy books?

burnt dragon
#

no

tawdry sky
#

why not

burnt dragon
#

because velocity would have to keep track of inventory state is which feasible

tawdry sky
#

why so

burnt dragon
#

to open a book you give the user a book and then tell them to open it and then remove the book, putting back what was there before

fossil sundial
fossil sundial
#

@opaque escarp ^ the client will essentially kick itself if it cant verify signatures it sent

old plover
#

Hello

#

It's possible disable this message [connected player] PLAYERNAME (/example:11111) has disconnected

bold wharf
#

Unless there is a config option, no

#

you'd need to setup a log filter

old plover
#

okay

#

ty

slow thistle
#

How do I send a Player to a RegisteredServer

bronze yoke
#

Player#createConnectionRequest

#

and then call connect or fireAndForget or whatever your use case is

slow thistle
#

how do you get the max player limit of a server or check if it's full

bold wharf
#

ping it

#

ofc, that won't account for perms which allow players to join when the server is full, so best you can generally do is to just try joining unless you wanna aim to fully respect the reported limit

old parcel
#

If you have ViaVersion, use latest dev build

steady trellis
#

i think i had this problem bc my encoding wasnt utf 8 or maybe it was smthn else idk

lusty tundra
#

How does Velocity check whether a plugin "appears to be Bukkit/Bungeecord", I'm trying to make a library and I do have plugin.yml and bungee.yml in the resources, but also a @Plugin annotation on the correct class

fossil sundial
slow thistle
#

Is Velocitys API thread safe?

magic forum
#

Anyone here knows what can cause this error?

craggy pecan
#

Except for things you aren't supposed to mutate concurrently in multiple threads (e.g. event objects)

candid shale
#

how do i execute a velocity command via chat-clickEvent

lusty tundra
burnt dragon
candid shale
bold wharf
#

try without the /

burnt dragon
#

that's definitely not it

#

all that click event does is make the player run that command, if you can also run it as a player then it works

bold wharf
#

well, command unknown would be not registered or no perms

burnt dragon
#

hence proxy/bukkit doesn't matter, the player is the one running the command so it'll go through both

bold wharf
#

if it runs asthe player themselves, that excludes that

tawdry sky
#

How to recieve a plugin message?

bronze yoke
#

didn't 1.19 add some kind of thing where you no longer need the / before the clickevent? Because they don't allow sending chat messages anymore

burnt dragon
#

no, now it's required

vestal raptor
#

Anyone got any idea what might be causing this?

bold wharf
#

all we can see there is that the connection to the server was closed in an unexpected manner

vestal raptor
#

Seems to be happening without the plugin too, strange.

#

Ah it's another plugin doing it.

median kraken
#

If compression is disabled on the server and enabled on the proxy, velocity itself will compress traffic?

vestal prawn
#

Compression = more cpu usage and less bandwith usage
So if you are on a local connexion (most of the time proxy <-> spigot) it's better to disable it since you have "infinite" bandwith

real pivot
#

Hey, anyone know how to check if a player is opped? Thanks!

burnt dragon
#

pretty sure there's an isOp method

fossil sundial
#

Wrong channel

real pivot
#

sorry, wasn't sure where to message

#

ill have a look though the API again, thanks :)

static flare
lunar quail
#

how can I make idea ignore that fields annotated with @Inject are never assigned?

burnt dragon
#

alt+enter, press right arrow on warning, press suppress for things annotated with inject

lunar quail
#

I added <writeAnnotations> tag to .idea/misc.xml and it worked

vestal prawn
#

So you don't need to @inject on the attribute

elfin gorge
#

Hello.
While player logging in,
I want to store the player's Client brand into database.
but Inside the PostLoginEvent
the getClientBrand() seems to return null (but if I do it in a commnad, it works (maybe I need a slightly delay or something))
Any solution?

    @Subscribe
    public void PostLoginEvent(PostLoginEvent e) {
        Player player = e.getPlayer();
        System.out.println(player.getClientBrand());
elfin gorge
#

yea I just discovered it mins ago
Thank you

fossil sundial
lunar quail
vestal prawn
#

for example Lunar Client will show as "lunarclient:version" but Badlion Client will show as "vanilla"

fossil sundial
fossil sundial
#

but you’re right

#

its about the intention to be identified

lunar quail
#

is there any way to remove (Velocity) thing that is always added after client/server brand names?

#

or to customize modification pattern if there is one

burnt dragon
#

no supported way, removing attribution is cringe

native knoll
#

is there a way to create a command that shows a GUI to player in velocity?

burnt dragon
#

velocity does not have inv support so, within the realms of the api, no it's not possible

maiden hawk
#

You can use protocolize

rich hawk
#

which isn’t supported fyi

magic forum
#

Bug in velocity: When client sends plugin messages right after receiving login success packet, and the backend server isn't in play state. An error.

#

What should happen, Velocity queues the packet to later be sent when the backend server switches to play state

fossil sundial
#

Already know about it- the entire play handler is due for a rework

#

We need quite a few queues

magic forum
#

Ah good. I have gotten a couple of issues that this is the cause

fossil sundial
#

The play handler is going to be a compound handler in the near future

#

Aka not a single class

#

I’d rather construct a handler from what’s needed for plugins to work

#

We were here before when clients sent commands before a server connection is established

#

That’s very stupid but can happen

fossil sundial
#

I know this may sound stupid

#

But I’d rather not queue messages if possible

#

This may include delaying login success until a connection is established for the first time

#

The API a doesn’t guarantee a lot of continuity

magic forum
#

Yea, whatever is best solution

#

I can reply to the guy that he should use a faster connection to the backend server

#

And that there is a fix coming soon

hot radish
#

Hey, is there a way to send player to another server from backend server level or would I need some kind of agent running on velocity + message queue?

bold wharf
#

yes, that

#

velocity implements the bungee messaging channel

hot radish
#

oh, okay, I though there's some dedicated way of doing that velocity-style. Thanks 🙂

native knoll
#

How can I communicate with the proxy server from any of its sub-servers?
Lemme explain
so I have 2 servers running on the proxy and those servers contain plugins
I would like to know how to get the server name that is configured in proxy.toml of the subserver the plugin is on
also how can I communicate with them using a class? can a class be loaded on all servers if I load it from a proxy plugin?

bold wharf
#

classes are not magically shared across JVMs

#

and you can use plugin messages for communicating, assuming you have a player

native knoll
#

hmm

#

it makes sense about JVMs but no its not about a player

#

its about getting a subserver's proxy name from a plugin on the subserver

#

not sure how thats done

#

Server.getName() does not give the name configured in velocity.toml

bold wharf
#

Basically

#

as I literally said

#

You can use plugin messages

#

BUT, you need a player connected to do that

#

otherwise, there is literally no means to get that info magically, you'd need to pass it in manually

native knoll
#

plugin messages
what do u exactly mean?

#

on player connection event?

bold wharf
#

it's a mechanism for sending custom data between, generally, a server and a client

#

but, the proxy being a proxy can sit in the middle and also (ab)use that feature

native knoll
#

i see

#

i've thought of a way i wanted to ask about not sure if its the best way to do that since i have no idea how to use plugin messages
using redis
basically onProxyInitilization i will bind all server names to their port key (port), value (name) to the redis database
and when i am on the subserver's plugin i would use redis to get the name of the server from its port
is this possible or am i wasting my time?

bold wharf
#

I mean

#

if you can map A to B, sure

lunar quail
#

does velocity shade mojang authlib?

fossil sundial
lunar quail
fossil sundial
#

I don’t see any usage that requires the full feature set

#

A few lines of code are usually enough to replace it

lunar quail
fossil sundial
#

We have our own impl of that so I don’t think it’s useful

lunar quail
#

using the whole authlib for a single class isn't a good idea ig then

lunar quail
fossil sundial
#

You should use what’s provided by the platform. Mojang is strict in their api limits for querying profile data

#

A few wrapper classes are probably a better idea- since you’ll be converting from each platform anyway

spring smelt
rich hawk
#

click event

#

on Conponent

spring smelt
#

thanks man

charred pulsar
#

In order for plugin messages channels to work do in need to register them like how they are done in bungeecord?

rich hawk
#

yes

charred pulsar
#

if its legacy channel should i put legacy:channelname

rich hawk
#

think so

charred pulsar
#

i just registered the channels but they seem not fire event when i send the plugin message from minecraft server

fossil sundial
charred pulsar
#

Legacy channels are for 1.12.2 or lower, but 1.13+ it needs namespace,MinecraftChannelIdentifier as i did everything as expected, cant get the event to fire

bronze yoke
#

isn’t it just ChannelIdentifier

charred pulsar
#

ChannelIdentifier is an interface

bronze yoke
#

ah yeah mb

oblique haven
#

and we can even use this for timestamp validation if we want to do that - we just have to implement it into that since it already keeps records

#

then we need to port timestamps to specific packets - so like in the piggyBack function we'd have some mapper of (priorTS, EnteredPacket) -> NewPacket or something like that

#

let me write up a PR to incorporate this into the chat building functionality

night forum
#

Hi anyone uses specific development environment i mean libraries and testing enviroments some frameworks or something

oblique haven
oblique haven
oblique haven
#

very unintrusive and should have the least amount of discrepancies with what's trying to touch it, going to run a bunch of testing with it tonight to see if I can get it to send out of order crap

night forum
oblique haven
opaque escarp
# night forum i mean i want to start project with full testing env and want to know what other...

I use JUnit/AssertJ and this is how I have it organized in case it serves as an example using the Velocity API https://github.com/4drian3d/KickRedirect/tree/main/src/test/java/me/dreamerzero/kickredirect

GitHub

Redirect your players to a server after a server shutdown - KickRedirect/src/test/java/me/dreamerzero/kickredirect at main · 4drian3d/KickRedirect

charred pulsar
hushed fiber
#

Velocity supports forwarding information about your players to your servers, such as IP addresses, UUIDs and skins.
are these the only things velocity forwards?

bold wharf
#

velocity forwards primarily the Ip and the UUID

#

the UUID thing is used in part for allowing the server to fetch skins (as well as identify players properly)

elfin gorge
#

How Do I listen to the received plugin message in Velocity?

I have this in spigot plugin and it works fine

        messenger.registerIncomingPluginChannel(this, "FML|HS", (s, player, bytes) -> {
            String result = (new String(bytes, StandardCharsets.UTF_8)).substring(1);
            System.out.println(result);
        });

But in the velocity, it doesn't work at all.

    @Subscribe
    public void dwdw(PluginMessageEvent e) {
        System.out.println(e.getData());
    }
fossil sundial
#

See this if you need an example

elfin gorge
#

Yes I did

#

Basically I sent these to the player

        player.sendPluginMessage(new LegacyChannelIdentifier("FML|HS"), new byte[]{-2, 0});
        player.sendPluginMessage(new LegacyChannelIdentifier("FML|HS"), new byte[]{0, 2, 0, 0, 0, 0});
        player.sendPluginMessage(new LegacyChannelIdentifier("FML|HS"), new byte[]{2, 0, 0, 0, 0});
fossil sundial
#

Did you register the channel

elfin gorge
#
public static ChannelIdentifier FMLHS = new LegacyChannelIdentifier("FML|HS");

    @Subscribe
    public void onProxyInitialization(ProxyInitializeEvent event) {
        server.getChannelRegistrar().register(FMLHS);
        // register other stuffs... 
   }

    @Subscribe
    public void PlayerClientBrandEvent(PlayerClientBrandEvent e) {
        Player player = e.getPlayer();
        player.sendPluginMessage(FMLHS, new byte[]{-2, 0});
        player.sendPluginMessage(FMLHS, new byte[]{0, 2, 0, 0, 0, 0});
        player.sendPluginMessage(FMLHS, new byte[]{2, 0, 0, 0, 0});
    }

    @Subscribe
    public void PluginMessageEvent(PluginMessageEvent e) {
        System.out.println(e.getData());
    }
#

the PluginMessageEvent doesn't work

#

But in Spigot, it reads response successfully

messenger.registerIncomingPluginChannel(this, "FML|HS", (s, player, bytes) -> {
            String result = (new String(bytes, StandardCharsets.UTF_8)).substring(1);
            System.out.println(result);
        });
charred pulsar
#

did you register your channel as outgoing too?

#

registerOutgoingPluginChannel

elfin gorge
elfin gorge
charred pulsar
#

no its is for spigot

#

if you are sending to proxy

#

you have reigster it as outgoing

elfin gorge
#

And Player response to Server -> I can't read response from Velocity but Spigot can.

elfin gorge
sacred ice
#

When I use this to get the users locale it always prints out en_US. When I change my language it stays the same. When I do the exact same thing on the paper side it works perfectly. Does anyone know what I have done wrong?

#

And the Method player.getEffectiveLocale() returns null every time. My problem is that I need to get the player locale when the player joins the network.

#

I use the 'ServerConnectedEvent' Event.

fossil sundial
#

you dont need to use a decompiler

fossil sundial
hidden gale
fossil sundial
# sacred ice Ah okay thank you. 👍

yea the locale is one of those things that will only be asserted by the client after a connection is already in the PLAY phase past the server connection events

#

you can set a custom default locale value with the setEffective…

#

but until then you dont know

sacred ice
#

Okay. 🙂 But is the PlayerSettingsChangeEvent fired before the Player establishes a connection with the paper instance? Because I want to get the Player Locale for a default language.

fossil sundial
#

no- it is fired after a server connection is already established

#

thats why I said in PLAY phase

#

the timing there is tight so we cant exactly change that behavior

#

its just how the client works

sacred ice
#

Yeah I understand. I will find a way to use it right.

lunar quail
#

is there any alternative to Bukkit.getMinecraftVersion() on Velocity?

fossil sundial
lunar quail
#

or latest protocol version

fossil sundial
lunar quail
#

yes, I see, thanks

lunar quail
#

not really a velocity dev question, but I get in a velocity plugin, so

what may be the cause of me getting NoSuchMethodError here? the method is here and the same signature :/

[15:10:20 INFO]: dataFolder = /home/user/velocity/plugins/cloud-api
[15:10:20 ERROR]: Couldn't pass ProxyInitializeEvent to cloud-api
java.lang.NoSuchMethodError: 'void org.yaml.snakeyaml.DumperOptions.setIndentWithIndicator(boolean)'
        at org.simpleyaml.configuration.implementation.snakeyaml.SnakeYamlImplementation.configure(SnakeYamlImplementation.java:182) ~[?:?]
        at org.simpleyaml.configuration.file.YamlConfiguration.setImplementation(YamlConfiguration.java:62) ~[?:?]
        at org.simpleyaml.configuration.file.YamlConfiguration.<init>(YamlConfiguration.java:52) ~[?:?]
        at org.simpleyaml.configuration.file.YamlConfiguration.<init>(YamlConfiguration.java:43) ~[?:?]
        at org.simpleyaml.configuration.file.YamlConfiguration.<init>(YamlConfiguration.java:33) ~[?:?]
        at org.simpleyaml.configuration.file.YamlConfiguration.load(YamlConfiguration.java:403) ~[?:?]
        at org.simpleyaml.configuration.file.YamlConfiguration.loadConfiguration(YamlConfiguration.java:174) ~[?:?]
        at <...>.loadConfiguration(<...>.java:85) ~[?:?]
        at <...>.onEnable(<...>.java:50) ~[?:?]
        at <...>.onProxyInitialization(<...>.java:47) ~[?:?]
        at <...>.Lmbda$1.execute(Unknown Source) ~[?:?]
        at com.velocitypowered.proxy.event.UntargetedEventHandler$VoidHandler.lambda$buildHandler$0(UntargetedEventHandler.java:47) ~[velocity-3.1.2-SNAPSHOT-153.jar:3.1.2-SNAPSHOT (git-74edac96-b153)]
        at com.velocitypowered.proxy.event.VelocityEventManager.fire(VelocityEventManager.java:598) ~[velocity-3.1.2-SNAPSHOT-153.jar:3.1.2-SNAPSHOT (git-74edac96-b153)]
        at com.velocitypowered.proxy.event.VelocityEventManager.lambda$fire$5(VelocityEventManager.java:479) ~[velocity-3.1.2-SNAPSHOT-153.jar:3.1.2-SNAPSHOT (git-74edac96-b153)]
        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) [?:?]
lusty tundra
bold wharf
#

yea, version mismatch

lunar quail
#

that class is shaded into my plugin's jar

bold wharf
#

one really should relocate their own deps

lunar quail
#

hmm, lemme try

naive lodge
#

Hello guys

#

i need any help

#

Can you someone help me?

#

but

#

i not found ip forwarding in velocity

lunar quail
fossil sundial
low pumice
#

Is there a simple way to translate all colour codes of a line ?

burnt dragon
#

you can use a serializer like minimessage

low pumice
fossil sundial
sharp blade
#

How should i load resources from plugin jar?

Like


getClass().getResourceAsStream("resource.txt");

``` - this is not working
rich hawk
#

try using the classloader

fresh nymph
#

is there any configuration api provided with velocity? If so can someone link me to the docs for that

half vine
# fresh nymph nvm figured it out

Please never ever answer to yourself with just

nvm figured it out
Always add a link / something that you found so that others searching through this channel / seeing you message can know how you got it to work / where the docs are / ...

fresh nymph
# half vine Please never ever answer to yourself with just > nvm figured it out Always add a...
    private ConfigurationNode config;

    private void loadConfig() throws Throwable {
        configFile = new File(getPluginDataFolder(), "config.conf");
        if (!configFile.exists()) {
            InputStream is = getClass().getClassLoader().getResourceAsStream("config.conf");
            if (is == null) throw new NullPointerException("Missing resource config.conf");
            Files.copy(is, configFile.toPath());
        }
        HoconConfigurationLoader loader = HoconConfigurationLoader.builder().setFile(configFile).build();
        config = loader.load();
    }```
hot osprey
#

Can Velocity register new server at "hot"? I saw that is possible with bungee core... I would like to create a command which add a new server to the proxy with the pterodactyl API.

bronze yoke
#

yeah, via ProxyServer#registerServer

lunar quail
#

is it safe to do blocking operations in LoginEvent handler?

fossil sundial
#

The client has a hard limit of seven seconds to complete login

fickle dome
#

Quick question: is there any official maven repos for the latest builds of velocity-proxy? I can't seem to find it anywhere official.

fossil sundial
#

Wait

#

-proxy?

#

That’s not meant to be published

#

Only the -api part

#

Keep in mind that the API is licensed MIT
But the proxy parts are licensed GPL

#

We don’t officially support plugins that use the -proxy package

fickle dome
#

thanks*

rich hawk
#

you can still use it

#

you just won’t get support for it here

#

as it’s internal

fossil sundial
fickle dome
#

I understand that I can access it but i was really hoping for a good way to implement it in a sensible way.

But yes, the reason I need access to the internals is because the two events I saw that could access commands didn't handle commands client <-> proxy <-> server

#

only from the client <-> proxy

fossil sundial
#

Wdym

#

Proxy plugins have full control over commands processed by velocity

#

Exg the command execute event is also fired if the command is meant for the server instead of the proxy

fickle dome
#

Well the issue I'm having is that both CommandExecuteEvent and PlayerAvailableCommandsEvent didn't fire when there was a command sent from client <-> minecraft-server

#

or when a Commands packet was sent from minecraft-server <-> client

#

respectively

fossil sundial
#

The only direction command packets are sent is client > proxy/server

fickle dome
#

And I couldn't find an event for that in velocity

#

well yes, i understand that i'm simply trying to illustrate the problem.

fossil sundial
#

If the commandexecuteevent is not fired then the command was issued by a plugin using executeImmediately

#

But there’s no other case where that happens

#

I don’t think I broke that

burnt dragon
#

i suppose it also wouldn't fire if the server executed a command as a player

lunar quail
fossil sundial
#

Fair

fickle dome
#

I think you misunderstand. I want to be able to intercept when a client runs /somecommand(tm) irrelevant if the command is registered on the proxy or is being forwarded to the server

burnt dragon
#

but like, getting -proxy in your classpath wouldn't help you with that situation anyway

#

so,,, the command execute event?

fossil sundial
#

Yea and that event should allow that

fickle dome
#

Hmm

fossil sundial
fickle dome
#

Well i'll give it a shot again. Perhaps i just goofed and din't register it or something stupid haha

burnt dragon
#

no it wouldn't ... if a server executes a command as a player then the proxy isn't involved at all whatsoever

fickle dome
#

I want to intercept that.

#

And as i said, the events velocity has seem to only fire when the command is registered on the proxy.

rich hawk
#

and the event should be xallled for that

fickle dome
#

This means I can't intercept a command that isn't registered on the proxy.

rich hawk
#

have you debugged it?

fossil sundial
#

Careful iirc velocity removes the / from commands found in that event

fickle dome
#

Ok so good news, It seems something has changed between the stable/dev-builds and it's working on the latest dev build without needing to use packets!

#

Sorry for bothering :)

fickle dome
#

Oh nevermind, I see what I was going on about now.
So on legacy clients (pre brigadier/1.13) command completions would be sent when a user runs /<tab> The issue is I can't manage to get TabCompleteEvent to fire when I do this.

#

And yes, I am registering the event

#

It does, however work if I listen for the packets (no surprise there)

rich hawk
#

tabcompleteevent doesn’t fire for >1.13 clients iirc

fickle dome
fickle dome
# rich hawk tabcompleteevent doesn’t fire for >1.13 clients iirc

Also, perhaps it should fire because /somecommand some-non-brigadier-completion is a valid use case for the latest version of minecraft. Otherwise there would be no way to detect it.

You also seem to be correct, even on a 1.19 bukkit server running /about E shows me completions for Essentials but no tab complete is fired.

bold wharf
#

well

#

there is an ask_server briagaider completion thing

#

the client completes /, from the command list sent to the client

#

but, /about E; should show completions if implemented properly

rich hawk
#

there's a seperate event for >1.13 afaik?

fickle dome
#

This basically breaks my plugin if the owner decides to run it on any server running VIA that is pre1.13 as it's only job is blocking commands.

bold wharf
#

ask_server is the only mechanism which fires tab completion which works on 1.13+

#

for 1.12 and before, you get to complete the entirety of /command

#

if you want to hide /command, you'd need to remove it from the list of commands sent to the player for 1.13+

fickle dome
#

The screenshot i just posted was from 1.19 on a 1.19 server

#

Here, i just double checked:

bold wharf
#

So, 2 second looks, the server on fires the tab complete event when the tab completion comes from the server

fickle dome
#

Yes, that is what i'm trying to modify

#

so, for example, if the above screenshot had Test Foo and Something I could remove a specific suggestion before forwarding it to the client.

#

This is very useful for servers who wish to de-clutter their commands when the plugins do not provide support to do it via permissions

#

One example of this is removing useless aliases like ehome in favor of home

bold wharf
#

oh, nvm, only fires if 1.12 and from the server

#

for 1.13 looks like you're just kinda screwed and would need to hijack packets

fickle dome
#

Well, I did get something working very well with packets. The only issue was that I couldn't find any official repos for velocity-proxy

#

well, updated ones at least.

bold wharf
#

we don't publish the impl to the maven repo, just the API

fossil sundial
fickle dome
#

and yes, i already do that.

fossil sundial
#

You need to use both

bold wharf
#

I mean, you're gonna need to ^

fickle dome
#

Ah yeah, I see what you mean and I already do that.

bold wharf
#

for sub commands you're gonna have to look at the structure AND deal with the packetry back and forth of the tab completion

fossil sundial
#

I know it’s inconvenient but that’s basically the only way to do it right since the implementation is so different

fickle dome
#

I already implemented that for both brigadier commands and pre-brigadier commands

#

well, not on velocity for the last one^^

bold wharf
#

I mean, for stuff on servers, this is really just best to deal with it on the server, as the server has all that context

fickle dome
#

I agree but people nagged me to make it compatible with bungee, then velocity.
And it did make sense at the time. One central config n what not.

bold wharf
#

well, yea, all is nice when you're not the one writin the code lol

fickle dome
#

I know right haha

bold wharf
fickle dome
#

Another quick question: my logger is formatting itself with the fully qualified class name of the plugin rather than the plugins name. What is the correct way to fix this?

bold wharf
#

get one with the name of your plugin instead of the class, basically

fickle dome
#

I see (I was just using the one the wiki recommended)
Cheers

oblique haven
#

I haven’t had the time

#

I tested specifically the chat queue by itself but haven’t tested my impl of it in velocity so I know the concept works and it also allows for spoofing, I will check both

bold wharf
#

I mean, I hate the overall thing

#

but, like

#

I don't really feel inclined to deal with the entire rip out I'd need to do for my solution

oblique haven
#

If you explain it to me I’ll try to impl it for you so we can play with the idea

#

The completable future thing just seems the most sensible here since it allows for the future to handle itself when it’s done

bold wharf
#

I mean, my own solution was generally just using a raw queue without the futures and basically just having a queue to pop off once the event handler fired

#

I'm just semi mentally dead and wanna see how 1.19.1 will generally apply to some of this mess

#

basically, we need to make sure that in the event of a cancellation of the event, that we're able to send out the relevant header packets, etc

oblique haven
#

That seems much more complicated

#

For no reason

#

Having to fire from a queue complicates everything and makes us actually act on things, the only time we can ever know for certain that packets are in order is if we’re receiving them in order from the client

#

If we spoof one then we need to fit it into that order, the queue impl does the same thing with another stage for us to handle.

#

We’re already passing around futures everywhere, why not make use of their completion stages..?

#

The event handler has its own whole executor

bold wharf
#

I mean, I'm not 100% aware of how futures work internally and all that

#

also never said firing from a queue

oblique haven
#

Basically an object wait object notify

oblique haven
#

I mean it effectively achieves the same thing I think

bold wharf
#

A precisely ordered queue which allows for outside entries into the ordered queue through piggybacking timestamps

#

that's redundant in 1.19.1

#

At least, with signed stuff, i think

#

So, shoving in our own custom stuff into that thing is not something I think that we need to care about

#

CPSH#710

#

That stuff was there for an exploit prevention

elfin gorge
#
Player#sendMessage(Component.text("&4test message&etest message&1test message&2test message&3test message"));

The color disappeared in the new line

bold wharf
#

don't mangle legacy text into a component

rich hawk
#

that shouldn’t even work

bold wharf
#

either use components properly or use the serialiser... ^

oblique haven
bold wharf
#

well, we'd need to deal with the time deposition BS

#

generally it just seemed more viable to use plugin messages for chat + commands

oblique haven
#

just by the way

#

unsigned commands still send a timestamp

#

the unsigned commands time delta for handling along with chat's time delta for handling is handled with this queue

#

and any entries made during a handle will be assigned to the next available position (spoofed commands)

#

if all commands a signed this chat queue becomes very simple - but if commands remain unsigned we're going to need a queue which doesn't lose its place

bold wharf
#

yea, but I'm not exactly sure that this is a good solution long term

oblique haven
#

well what's wrong with it ig

#

maybe I could make it better

bold wharf
#

kinda relying on the fact that mojangs handling of that stuff is kinda shitty

oblique haven
#

well it's just assuming the client is sending to us in the correct order (which is already verified)

bold wharf
#

i.e. it's just stealing the last time and praying that mojang doesn't prevent that from being done in the future

oblique haven
#

well we could also just add a millisecond

#

if it's unsigned it doesn't matter

#

the only way to stop that is to just sign all of the commands

#

but I don't think that's their purpose

#

if we need to drop "stealing the last time" we can just drop the piggyBack method and it all works the same anyways

#

the queue doesn't rely on things being pushed into it to work - and it will still deal with time deltas across the command handler(s)/chat handler(s)

#

I don't think the solution I made is really "hacky" it just solves order between the client->server communication, and it will always work with signed information, so it's pretty future proof. Even if they remove timestamp hijacking, then it should be fine since it will cause earlier issues than that, and as I said before it'll still work in that case.

bold wharf
#

Its not hacky as much as it's just relies on somewhat janky logic in the server

bold wharf
#

the part where mojang only cares about time going backwards

oblique haven
#

there's no logic in the queue

oblique haven
#

they can't verify system time against player time

#

(oops sorry for pinging you like 3 times, didn't realize)

bold wharf
#

no, but they coulda and maybe shoulda verified that time went forwards

oblique haven
#

Time will “go forwards”

bold wharf
#

I mean, sure, I guess

#

but that's somewhat part of why I wanted to just move that stuff over to using plugin message

oblique haven
#

I mean I’d wholly rather get velocity generic across servers and not require paper as a backend

#

I don’t like the idea of adding more stuff to plug-in messages to make it work when there’s better viable vanilla solutions

#

Forwarding makes sense, only way to do forwarding is through a custom session server or plug-in messages, but chat being there doesn’t make sense

#

I also think we should at least try to keep things at spec rather than re-implementing it

#

I do understand the plug-in message method though and do know it would be rather easy to do ^ but there’s just ways to do it without requiring backend impls so we should probably take it

bold wharf
#

I mean, we just make it part of the forwarding spec for velocity

#

and then if you wanna say that you're compat with velocity, you have to implement it

#

I mean, am just in a weird position where mojangs system has me iffy in general, especially as it's still a moving target

oblique haven
#

Yeah I get it

#

It just feels really restrictive to me

#

I think I like my solution better, I’ll throw it in a PR maybe later today and we can discuss in there other options

#

I think we should make a list of options and their actual raw benefits

bold wharf
#

Yea, I mean, it has the same general effect as mine, just, uses futures, which, futures are something which makes me iffy too lol

oblique haven
#

Haha

#

Futures are basically notify based stage handlers for an asynchronous process

bold wharf
#

I mean, they just get to be a bit of a clusterfuck to pick up what is going on, which is part of my iffyness for your thing is that it generally just looks kinda messy

oblique haven
#

Absolutely

#

Futures can be better understandable you just have to write it in a certain way which I can do

#

Honestly for this it’s probably all about formatting and adding comments

#

But we can push out a bunch into real functions

oblique haven
#

do note, a future can have multiple whenComplete callers

#
  public static void main(String[] args) {
    CompletableFuture<String> future = new CompletableFuture<>();
    future.whenComplete((string, throwable) -> {
      System.out.println("When complete 1: " + string);
    }).whenComplete((string, throwable) -> {
      System.out.println("When complete 2: " + string);
    }).whenComplete((string, throwable) -> {
      System.out.println("When complete 3: " + string);
    }).thenRun(() -> {
      System.out.println("When run 1");
    }).thenRun(() -> {
      System.out.println("When run 2");
    }).thenRun(() -> {
      System.out.println("When run 3");
    });
    future.complete("test");
  }``` for example this prints out everything listed, 1-3 for both, so we can chain appropriately
bold wharf
#

ik how futures work

oblique haven
#

okei

bold wharf
#

but, yea, that generally looks cleaner, for cancelled events do note that we will still need to broadcast some stuff out

oblique haven
#

I'm only putting the chat queue in the ClientPlaySessionHandler

#

we should also move the validation of timestamp order into the chat queue, that way we can validate through the queue rather than having a held timestamp in the session - tracking previous timestamps aren't great but like, hijacking needs timestamps to use which are known

bold wharf
#

back to the client

#

like

#

all clients

#

urgh, that's gonna be ass to deal with

oblique haven
#

How would you feel about the move from:

      future.thenApply(item -> new WrappedPacket(previous.timestamp, packetMapper.map(previous.timestamp, item)))
          .exceptionally(throwable -> new WrappedPacket(previous.timestamp, null))
          .whenCompleteAsync(writePacket(connection), connection.eventLoop())
          .whenComplete((packet, throwable) -> awaitedFuture.complete(throwable != null ? null : packet));
```to:
```java
      WrappedPacket.wrap(previous.timestamp, future.thenApply(item -> packetMapper.map(previous.timestamp, item)))
          .whenCompleteAsync(writePacket(connection), connection.eventLoop())
          .whenComplete((packet, throwable) -> awaitedFuture.complete(throwable != null ? null : packet));```
#

not sure which is cleaner

bold wharf
#

my one concern is chat plugins on the proxy, if they cancel packets and send them themselves

oblique haven
#

if someone is messing with internals, let them learn to mess with those internals

bold wharf
#

well, issue is that in 1.19.1, if somebody cancels chat packets, we still need to send information to all clients

oblique haven
#

really?

bold wharf
#

Yes

oblique haven
#

hm okay

hot osprey
#

why I can't override execute function in a class which implements com.velocitypowered.api.command.Command ?

oblique haven
#

well I mean that can be done in the process chat handler

#

that can be outside of the queue

bold wharf
#

You need to send a header packet in all of the clients involved

oblique haven
#

you can pass null to the queue and it will be fine with it

#

so we send null to the queue and send info to the clients

#

oh crap are we going to have to have knowledge of all the clients on the server

bold wharf
#

so, in .1, the chat works by basically storing a ref to the previous message to retain a "context"

oblique haven
#

makes sense

bold wharf
#

the client will keep iterating that and basically referencing the last chat packet it sent

#

and so, if a chat is cancelled, we still need to send out the header so that clients can keep track of the context

oblique haven
#

hm okay

#

so I wonder how we do that then

#

so with that we probably have to use the plugin channel to emit the header

#

but I don't think we need to verify they're on velocity, they can just ignore messages

#

we can just send something like velocity:chat_cancel_header and send the key ref to forward to the clients

bold wharf
#

hm?

oblique haven
#
          } else if (signedChat != null) {
            ByteBuf bufMessage = Unpooled.buffer(signedChat.getSignature().length);
            bufMessage.writeBytes(signedChat.getSignature());
            return new PluginMessage("velocity:cancel_chat_header", bufMessage);
          }
          return null;```
#

like this

#

then send the plugin message from proxy -> server

bold wharf
#

Ah

#

wait

#

I don't see why that's neccessary

oblique haven
#

you said it's necessary to send the header

bold wharf
#

if cancelled on the proxy

oblique haven
#

there's no way for velocity to know all the players involved

bold wharf
#

this ofc creates many dozen issues

oblique haven
#

I mean we can block incoming client plugin messages if they're on velocity:

bold wharf
#

Like, on velocity if somebody "denies" the message, do we broadcast that from the proxy?

#

Like, technically, we should do that

#

but, technically, that is kinda gross

oblique haven
#

the proxy should never assume it knows about all the players on a specific connection

#

that's not a good idea

bold wharf
#

well, that's part of the issue

#

I'm thinking that we just find a way to delegate that over to the plugin

#

I don't see a sane way to handle this mess

oblique haven
#

so if a plugin is cancelling a chat event it is in charge of broadcasting the signature update?

#

wait

#

I'm confused now

#

okay nvm I think I got it now

#

so cancelling chat on the proxy should be a huge deal now and we should probably throw red flags and tell people to be careful

#

I think that letting people be in charge of the broadcast is fine if the paper api provides a way to do that cleanly

#

maybe paper should have a paper:update_chat_ref

bold wharf
#

Well, as said, chat messages now store a ref to the last chat message

#

if you cancel a chat message and don't send out the updated refs, the clients next message is going to refer to a chat message which doesn't exist to anybody, thus breaking that chain

#

so, now, if you cancel a chat packet from the server, or, proxy here, you now need to ensure that you send out the relevant information to clients to say "hey, heres the current ref from the client", that way the next chat message will still have a valid part of the chain

#

prepare to be blinded

#

specifically the "is player a recepient"

#

"is recpient" also really needs to extend towards cancellation on the server

#

but, the question here is how do we deal with this on the proxy too

opaque escarp
bold wharf
#

no

#

it's not complex

#

just arse

slender cargo
#

not complex for paper developer

#

its not really complicated

#

probably you're right

fossil sundial
#

@oblique haven the queue is good but two issues, it has to work for signed command components too and we also need to consider the signed suggestions

oblique haven
#

Signed command components will sign with their own time stamp, the only thing it modifies is unsigned

#

What are signed suggestions?

#

The queue is just a packet queue really, it ingests any packets and maintains their order with event handlers in the mix

#

That’s all it’s doing so we can stretch it for whatever we need

fossil sundial
oblique haven
#

I don’t think I understand

#

Can you explain how suggestions are apart of this

#

That’s the part I’m missing, and how they’re working

fossil sundial
#

If no suggestion/decorator then a literal is signed

gloomy junco
#

Hey guys!
Can you please tell me how can I control who will receive the message in the PlayerChatEvent?

#

or should I do ChatResult.denied() and then send the message myself to the players I need?

fossil sundial
tulip scarab
#

Hi, may I ask does anyone have experience with HEX RGB? sadCat

#

I'm working with Velocity for the first time and doing support for Velocity, but I don't know how to solve hex rgb on Velocity

craggy pecan
timber tartan
#

Is it possible to modify the logger? For example instead of "INFO" it says "DEBUG", I want to make a debug for my plugin and I have created a custom ConsoleHandler + Lombok but I can't modify that, I have to add after the name of my plugin "DEBUG" to know that it is the debug although at the beginning it says "INFO" and that's why I don't think it's the most appropriate thing.

https://i.gyazo.com/945974dd37bbb87f9082d5de8efaad42.png

rich hawk
#

use the appropriate logging level?

#

use debug instead of info

#

??

timber tartan
#

Debug -> Info -> Warn -> Severe

#

If you try to use the "Config" which is really the debug I think, you won't be able to use the current bukkit logger

covert folio
#

wut

timber tartan
#

So I have made a custom consoleHandler but I need that instead of INFO, I get DEBUG when I use the DEBUG. Because if I use the log.info I get INFO on the left, but if I use the log.fine for example I still get info too, and I don't know if it's possible to change that.

covert folio
#

Are you talking about velocity dev ?

timber tartan
#

"INFO" I think this is the default level in bukkit and I don't know if it is possible to change it

#

oh sorry

#

I thought it was the paper-dev channel lmao

#

🤦‍♂️

oblique haven
#

Since the class is just a packet queue we can have it go in and out either way

dire saddle
#

Is there a way to get the ProxyServer instance/a plugin instance from a static context?

rich hawk
#

yes

#

by doing it yourself

dire saddle
#

I'm not aware of anyone else writing my own code, but ok

what I meant is having a way to get any plugin's instance without having an instance of the ProxyServer at hand, eg. on Bukkit: Bukkit.getPluginManager().getPlugin("myPlugin");

robust mural
#

ProxyServer != Plugin instance

dire saddle
winged pike
#

any documentation regarding toml and velocity?

amber yacht
#

Does running a Scheduled task run the task on a separate thread?

#

Or multiple different threads, because I keep getting the feeling that code is being skipped or run in the wrong order ...

sour current
#

iirc tasks use a thread pool

hard vortex
#

is there a way to set the motd component colors to custom RGB colors?

lusty tundra
#

Yes, use static factories from TextColor

opaque escarp
#

ProxyPingEvent#setPing(ProxyPingEvent#getPing().asBuilder().description(MiniMessage.miniMessage().deserialize("<gradient:green:blue:#FF0F00>gradient motd").build())

lusty tundra
fluid oxide
#

In the docs, there's written a hint:

Registering an object as a listener 

server.getEventManager().register(plugin, listener);

In my IDE, this server variable isn't known. Any solution to this?

#

I got this currently:

public class MainClass {

    @Inject
    private Logger logger;

    @Subscribe
    public void onProxyInitialization(ProxyInitializeEvent event) {
        server.getEventManager().register(plugin, new ListenerClass);
    }
}
#

ah, nvm. one scroll further there's the explanation.. Sorry 😅

heady mortar
#

I'm trying to get a Player object but got ConnectedPlayer which class I dont have access (com.velocitypowered.proxy.connection.client.ConnectedPlayer)
got that result with this code

public class MyCommand implements SimpleCommand {
    @Override
    public void execute(Invocation invocation) {
        CommandSource source    = invocation.source();
        System.out.println(source.getClass());
    }
}
burnt dragon
#

instanceof time ?

heady mortar
#

trying to learn velocity, I just want to get a Player object to develop some simple interactions using commands

heady mortar
burnt dragon
#

how much java do you know?

heady mortar
#

actually enough to develop some simple apps

#

about 6 months to 1 year of experience with java

heady mortar
#

but I want a Player instance, but got ConnectedPlayer

#

class which dont is included in the api

slate hamlet
#

But ConnectedPlayer implements Player

heady mortar
#

didnt found anything in the 3.0.0 docs

#

but if ConnectedPlayer implements Player, invocation instanceof Player should result in true?

#

in the case invocation.source()

#

just found why my code wasnt working properly

#

tnx

fossil sundial
# heady mortar in the case invocation.source()

If you’re using java 17 you can do
if(invocation.source() instanceof Player player) {
player.disconnect(Component.text(“We don’t like players”);
}

(Aka typecast in the condition)

heady mortar
#

I think the old way is cleaner but its nice to know I can do it that way too

fossil sundial
light tendon
#

What is the velocity messaging channel name?
like when a spigot plugin is trying to send message through the channel like BungeeCord
to switch servers

rich hawk
#

same as bungee

fossil sundial
#

no need to reinvent the wheel and enough plugins use it for us to just roll with it

dire saddle
# robust mural What is your aim?

I need to get the server instance to register listeners. I can't do this directly because I'm making an extension to a plugin that doesn't directly give me the velocity server instance. The plugin itself is quite extensive and refactoring it to give me the proxy instance would be almost impossible since the common module registers the extensions and the platform submodules don't have anything to do with the extensions.

fossil sundial
charred pulsar
#

I am having weird problem trying to solve, i have plugin messages being sent correctly in locally hosted environment but, some people are complaining that no data is being sent back, i found this is the case in friend server too, not sure how to debug this

fossil sundial
#

Show your code?

charred pulsar
#

I first did some logger info on event, does not seem to fire, but locally it does

tepid tusk
#

[16:54:19 INFO]: [initial connection] /IPHERE:PORT has disconnected: multiplayer.disconnect.missing_public_key

bold wharf
#

p i n s

silver wedge
#

are book packets possible in velocity?

burnt dragon
#

packets? sure - but opening a book isn't available in the api at all

silver wedge
burnt dragon
#

sure you can

#

unsupported tho

silver wedge
#

okok, thank you

agile ore
#

hi how can I change this writing? thanks I await response (to your answer please tag me)

atomic leafBOT
oblique haven
#

@agile ore ^

twin ingot
#

Hey have you guys encountered the problem that the DisconnectEvent event was not always firing?

fossil sundial
uneven plover
#

how can you get total players online a velocity network?

sour current
#

proxyServer.getAllPlayers().size()

craggy pecan
agile ore
# oblique haven <@456226577798135808> ^

i mean how can i change the proxy version name when example i view it on namemc.com ?? example how can i change the version name visible to users maybe a user enters with a version that velocity does not support but exits as this example thanks and awaiting answers

the server uses velocity)

burnt dragon
#

ping event has a version method

agile ore
burnt dragon
#

by using the version method in the ping event

agile ore
burnt dragon
#

im not writing the code for you

#

there is a ping event, listen to it and modify the result to set the version string to something else

agile ore
burnt dragon
#

it's ProxyPingEvent irrc

agile ore
burnt dragon
#

does that say ProxyPingEvent

agile ore
burnt dragon
#

are you a developer

agile ore
#

sorry for the pings)
ù

burnt dragon
#

like a plugin developer

agile ore
#

i am not a java developer or plugin

burnt dragon
#

then why are you asking in the velocity development channel

agile ore
#

because in theory the developers should be able to "" explain this to me "

burnt dragon
#

i literally did

bold wharf
#

in practice very few people have the will/time to teach java to everybody who wants to use this channel

burnt dragon
#
  1. learn java
  2. learn velocity plugins
  3. listen to event
  4. change version
bold wharf
#

as I said, there is a plugin out there which probs fits your need in the other channel

pseudo escarp
#

After modifying the UUID using GameProfileRequestEvent#setGameProfile. The chat message signature will use the modified UUID or the original UUID. Does the client know its own UUID modification?

static flare
#

hi i am developing a plugin but it has a error that
com.velocitypowered.api.plugin.InvalidPluginException: Did not find a valid velocity-plugin.json.
i follow the doc and use kotlin for devlopment

deft ore
robust mural
rich hawk
#

use kapt

static flare
bold wharf
#

Kotlin uses kapt

static flare
#

well....what is kapt?

bold wharf
#

It's how you specify an annotation processor in kotlin

#

See their docs/look for projects on GitHub for an example, I don't remember the specifics

static flare
#

ok thanks

#

it works

#

and could i use ShadowJar for velocity plugin?

bold wharf
#

Yes

#

A jar is a jar

oblique haven
# deft ore

please contact minehut support for this before reaching out to velocity support

#

Minehut's velocity configuration is generally unsupported and should usually be vetted by us before reported to velocity, especially login issues like these

tawdry sky
#

How to listen for plugin messages on velocity? both from the client's mods and the proxied servers

#

and if a client mod sends something over a plugin message channel that say bungeecord uses, could it be possible to hijack it and access unauthorized places? (such as a build server)

bold wharf
#

well, the bungeecord channel, no, because the proxy validates that the sender is a server and doesn't let it be sent to users

fossil sundial
#

Changing the uuid then will just break signature

tawdry sky
bold wharf
#

instanceof the source object

#

see the javadocs

#

I don't remember, either there was an event or some proper registration system

#

there was a gist somewhere with an example

tawdry sky
bold wharf
#

No

tawdry sky
#

Atleast I tried

bold wharf
#

I don't have a copy of it saved somewhere, maybe five or somebody does

#

I just used the saerch for register

rich hawk
#

pin?

tawdry sky
#

Dumb question, but how do I get the Player object if the server sent the plugin message?

bold wharf
#

well, they would be the target

tawdry sky
bold wharf
#

something like that

tawdry sky
#

Cool

fossil sundial
#

That’s the intended way

pseudo escarp
#

But I wonder if it's possible to do something like a UUID conversion (like NAT) that just spoofs the back-end server UUID. Does this break the chat signature?

fossil sundial
pseudo escarp
#

Is there any change between 1.19.1 and 1.19, you said it no longer works on 1.19.1

fossil sundial
#

Yea exactly that

ocean badge
#

server generate key for all clients, and re-signed all the message?

fossil sundial
#

The uuid form mojang is part of the signature

#

No we can’t do that

half locust
#

by definition of the system the key is private

fossil sundial
#

It’s a lot more chaotic

half locust
#

if servers could resign that would defeat the point

ocean badge
#

what was the way other clients get others public key?

fossil sundial
#

Tablist

ocean badge
#

so we just swap out the key in tablist and it should work?

fossil sundial
#

No

#

Because the uuid is part of the key signature

ocean badge
#

sign(uuid+ public key)?

fossil sundial
#

Key + UUID + Expiry date > Signature
Signed against Yggdrasil

#

Signature is generated by Yggdrasil

#

Not possible to spoof

ocean badge
#

we also swap out the signature too?

fossil sundial
#

You can’t

#

You’re not Yggdrasil

half locust
#

the entire point of the system is only the player can sign it. There's no way around it

ocean badge
#

oh i know private key for signature is hold by YggdrasilSEED

fossil sundial
#

yes

#

Yggdrasil public key is hard-coded in the mojang authlib

ocean badge
#

ok, I know why we can not swap it1f421

#

only can done if we use a modified client1f421

fossil sundial
#

Yes

#

And a modified server

#

(And modified proxy)

#

I’m dreading writing the player key manager

#

Alas it has to be done

pseudo escarp
#

I just want to do one thing, I need players to load playerdata by my special uuid, I don't want to change the file name, because it will cause the pets in the world to not know the owner.

#

thank you all, i will find a solution

shadow pumice
#

scoreboard API for velocity please

fossil sundial
#

But that’s rather low on the list atm seeing how massive the 1.19.1 update is technically

tawdry sky
#

How to use Command args with SimpleCommand?

tawdry sky
#

Fr?

#

Well shit finally

craggy pecan
fluid oxide
#

Is there a documentation on creating configs and other resources? Pls ping with answer

craggy pecan
#

For configuration files, see the Configurate wiki on GitHub

#

What do you mean by other resources?

fluid oxide
#

idk some extra config.yml for menus or something