#help-development

1 messages · Page 1321 of 1

lavish wing
#

Yeah, there s no spigot for 1.3.2
But spigot contains bukkit repo, which has 1.3.2

sly topaz
lavish wing
#

I have very big community for these versions

#

And I need to make my own fork to fix a lot of bugs and expolits

sly topaz
#

it didn't have much of an ecosystem back then, and all the plugins that support that version are probably lost to time. Chances are you are going to have a better time just running LegacyFabric which has an active community (very small, but active nonetheless)

lavish wing
#

Never heard about LegacyFabric, will check it later

sly topaz
#

welp, if you already have plugins developed for that version then it'll be a chore to port

#

so you're stuck with Bukkit I guess

lavish wing
#

Does LegacyFabric need custom client?

#

modded*

sly topaz
#

it is just fabric, but for legacy versions

#

fabric can load mods both on the server or the client, what determines if you need a mod on the client side as well is just whether you do something that's out of the scope of the vanilla protocol

lavish wing
#

I got it. Then it's better to use bukkit, my players using forge and vanilla clients

sly topaz
#

I don't think you understood what I meant. You don't need a modded client as long as you don't do anything that would break the protocol

lavish wing
#

oh

sly topaz
#

that's pretty much what plugins are in the end, server mods

violet wave
#

Will spigot 1.21.11 be completely embracing mojang mappings or will it be keeping custom spigot names?
I hope for the former.

shadow night
#

I don't see a reason to stay with spigot names

sonic goblet
#

?paste

undone axleBOT
sonic goblet
eternal oxide
#

Asynchronous chunk updates!

#

you have a bad plugin. Or one which is not compatible with Spigot

wet breach
#

they are running a modded client

#

I assume they have two types of servers. One forge and another spigot and connected to the one they thought was forge

slender elbow
#

huh

wet breach
#

a mod that is known for causing that specific error is Better Compatibility Checker

sonic goblet
#

I see, it says "Forge Server Log" but we only have a Spigot server and I've been running the same plugins for ~2 years now. Nothing new.

wet breach
#

you sure you don't have a modded client?

sonic goblet
#

Like that player is a modded client joining?

wet breach
#

There is only two likely things causing that error. Either they have a modded client or their player data is corrupted

eternal oxide
#

Its a server side error about an Async world modifcation. A modded client can not do that. Its a plugin not compatible with Spigot. Likely a worldguard for paper or something silly

wet breach
sonic goblet
#

I see, It's concerning that they were able to bring the server to a halt with that. I had to restart it completely

#

Essentially a ddos lol

wet breach
#

Yeah corrupted player data wouldn't cause the server to halt

#

it would just cause the player to not be able to join along with that error

#

a modded client can indeed cause a server to do weird things sometimes and thus why you should invest in packet inspection related things

#

Server does alright most of the time, but sometimes not good enough

#

also, you can do nefarious things sometimes with just packets alone so always good to have packet inspections anyways lol

young knoll
#

How does a modded client trigger a server to modify the world async

wet breach
#

the server isn't trying to modify the world async, its trying to load/spawn the player in

#

but it can't because the data the client is sending is not correct

slender elbow
#

lol

slender elbow
#

yeah from what i can tell this is just a good old spigot bug, enabling the code of conduct just triggers that on spigot, gj

wet breach
#

guess, I should make note of that as something else to cause that error that is quite vague

sonic goblet
wet breach
sonic goblet
#

Ya haha

wet breach
#

well, now I have that added to my notes

mortal hare
#

honestly i think im ditching intellij in favour of just vscode

#

eclipse jdts lsp server is more than enough for me and i do most of the things in cli (like maven or gradle tasks) anyways

quaint mantle
#

honestly i think im ditching vscode in favour of nvim

mortal hare
#

nah

#

that's too far for me

#

the reason why its too far is not because of nvim's nature of being cli, but because its not popular enough to get first class support of LSP's

quaint mantle
#

Honestly I sometimes use mouse instead of memorizing a key in nvim

mortal hare
#

all LSP's nvim provides in extensions are mostly ports from vscode

#

thus they work less optimal than they would on vscode

#

also vscode can be run in the cloud

#

its nice to have quick notepad in the cloud just to do configuring or replacement logic with regex

quaint mantle
#

Cool but ssh

half portal
#

Looking for a dev that knows how to sk and config

chrome beacon
undone axleBOT
idle condor
#

?paste

undone axleBOT
mortal hare
#

why do people not write assert in java? I know that there's unit/integration testing but having something something like this allows to produce debug builds where you can easily reproduce the bug sounds... awesome?

#

i feel like it should be supplementary to the unit tests

idle condor
#

im trying to detect a right click but no matter what i do it doesn't work anyone got any idea?
Paste Dev Link

eternal oxide
#

^ not the correct place to advertise. Post it on teh spigot site

mortal hare
#

its awesome for cases where there might be a bug due to impossible case (like nullability, invalid state, etc.)

#

by adding asserts for invalid states, you can produce stack traces with a debug for a cases which might be not needed if the behaviour was correct in a first place

#
public static Email from(final String address) {
    assert address != null: "Provided address argument is null";
    ...
}
#

lets say someone passes null into that method, you get github issue mentioning some kind of regression

#

you ask the OP to enable assertions and produce a stack trace

#

that like saves a lot of debug time just by enforcing strict checking which might not exist in production in a first place

#

it doesnt replace unit or integration tests

#

it adds a layer on top of them

#

to allow for easier manual testing

mortal hare
# eternal oxide assert does nothing at runtime
package lt.gathertime.server.value;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class Email {
    private static final Pattern PATTERN = Pattern.compile("\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b", Pattern.CASE_INSENSITIVE);
    private final String value;

    private Email(final String value) {
        assert value != null;

        this.value = value;
    }

    @Override
    public String toString() {
        return this.value;
    }

    @Override
    public boolean equals(final Object value) {
        if (this == value) return true;
        if (!(value instanceof Email email)) return false;
        return Objects.equals(this.value, email.value);
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }

    public static Email from(final String value) {
        Objects.requireNonNull(value, "Email address value cannot be null");

        Matcher matcher = PATTERN.matcher(value);
        if (!matcher.matches()) {
            throw new IllegalArgumentException("Email address value is not of valid format");
        }

        return new Email(value);
    }
}

for example lets look at this email class. Public API (static smart constructor method) checks for nullability, but internal implementation uses assertions just for development purpose only to debug something in case there might be a need for at runtime.

thorn isle
#

I agree, asserts are an underutilized feature

mortal hare
#

this is a simple example, but if you lets say have multiple smart constructors with different varying levels of impl, this can save lots of debug hours

thorn isle
#

My guess is that people avoid them because as newbies they're told to never use asserts

#

In the same way we often hear "static bad" here

#

Both are tools for their jobs but you have to decide where to use asserts vs exceptions judiciously, and it's not a judgement call that's easy to explain to a beginner

#

So you end up telling them to just not use asserts

#

the other part is that, if you've bothered writing up validation logic, even if it's just for your internal affairs and "shouldn't" be needed outside of testing, you might almost as well just keep it there outside of testing anyway

#

the only downside is there being a performance impact from the actual validation logic, which in some cases can be negligible even for relatively hot code

#

e.g. that null assert on the email might as well be replaced by an exception, and the behavior of the program would only improve or remain unchanged at worst, never degrade

#

specifically, someone introducing the regression would have the code fail-fast immediately without the need to tell the end user to enable assertions

#

so although i do use asserts, i only usually use them for very hot spots, or for complex validation checks that'd have a real world impact on performance if shipped to prod

mortal hare
# thorn isle e.g. that null assert on the email might as well be replaced by an exception, an...

well yeah the cost of statements is neglibible on production, but i see it more like a semantic highlight for a developer too. If i know that something is exposed public, i use if statements with exceptions, if something that's internal that might go bad, i just use assertions just because it instantly implies for me that hey, theres might be the bug with the code you're looking at and not from some external source misbehaving

thorn isle
#

that's valid as well

mortal hare
#

it allows me differenciate internal misbehavings from external ones

thorn isle
#

there's never a clear-cut best way of doing these things; when in rome

mortal hare
#

iirc it also gives some sense to the IDE's of what data needs to be passed, so if you have private methods, it can also help the IDE catch the bugs for you

#

but so does annotations but annotations are less flexible to the demands of the domain though

thorn isle
#

one funny thing i use assert for it static flow control analysis

mortal hare
#

there's @Contract in jetbrains but who tf uses that and its very hard to really write them properly

thorn isle
#

it's a bit backwards, but suppose you have a bunch of if else spaghetti and other flow control, and you want to statically ensure that e.g. a != b, a and b being values modified somewhere within the flow control in easily unintuitive ways

mortal hare
#

i'll take that in mind

thorn isle
#

add the condition as an assert, and if it shows up with a warning saying "a != b is always true", you know your logic is right 🤡

#

the downside is that now you have a warning in your code

mortal hare
#

that's actually so smart

quaint basin
#

How should I create an RTP plugin? If x can be the minimum to the maximum value in the world, won't that use a lot of disk space/load many chunks?

thorn isle
#

what now

#

i'm not sure what you're asking exactly, but the way how rtp plugins typically work is by picking a random position, validating it, and retrying it if it isn't valid

#

depending on how strict your validation is, this can require few or many chunk loads

quaint basin
thorn isle
#

if it's a truly random tp, sure; personally i use a ring with a gaussian distribution tapering off the farther out/in you go from the ring

#

use whatever distribution fits your use case

thorn isle
#

i mean i don't pick a position from an uniform random distribution

#

some locations are more likely than others

quaint basin
#

In that case, I think I need to make the scenario that covers the entire world because, since it's going to be a resource-based world, it's good to spawn in a place that has resources and hasn't been explored yet (although this world will be reset daily)

thorn isle
#

if this is vanilla, i'm not sure if that's necessary; even if one or two players chop trees or mine ores, the area won't be completely exhausted

thorn isle
#

if you really want to avoid sending players to locations that players haven't visited already, you can keep track of the areas where players have gone and check that in your location validation logic

#

do it asynchronously and ahead of time and you won't have to delay the teleport for the search

quaint basin
#

Ah, right, I understand now. It's to perform the verification in a "single tick" - in this case, there is no tick because it's async

thorn isle
#

and if the world is large enough, a purely random distribution is probably good enough; the chance that any two players get sent to the same location is fairly low

quaint basin
#

Is there a risk of killing the async thread, even if the probability is low?

#

If I implement this validation using a while loop logic (as you're suggesting, but async) instead of splitting the validation into different time points

#

In my view, I can kill the async thread even if the probability is low

thorn isle
#

kill?

young knoll
#

Just make the world smaller and reset it often

quaint basin
thorn isle
#

threads don't die by sleeping

#

either way, i would use an ExecutorService rather than a while loop in a dedicated thread

quaint basin
thorn isle
#

this way thread lifecycles aren't your problem and even if they "die" from being idle in the executor's thread pool, the pool will create new ones on demand

quaint basin
thorn isle
#

threads die when

  • the jvm dies
  • another thread kills it via the deprecated kill/stop methods
  • an uncaught exception reaches the top of the call stack
quaint basin
#

I think it's simpler to just validate each tick in the main thread and try for a valid location per tick

thorn isle
#

none of these should happen in normal operation

ivory sleet
#

@mortal hare a problem w assert is that it yields AssertionError not sure if that was mentioned

#

well it’s both a problem and a benefit depending on how u look at it I suppose

thorn isle
#

if it's used what it's supposed to be used for, it's a benefit

#

errors typically shouldn't be caught, so an assertionerror will terminate whatever is going on

quaint basin
thorn isle
#

aside from actually logging players breaking ores/harvesting resources in areas, there's no way around that

#

it does guarantee, however, that the area a player teleports to is untouched

#

the downside is that if you don't reset soon enough and your world is too small, you may completely run out of valid destinations

#

but again, i think just throwing everybody into purely random locations within a range is good enough; it's fairly unlikely for two players to teleport to the same place

quaint basin
#

What I was initially going to do is set the location to x = minX of the world + random.nextInt(maxX - minX + 1). The same for Z. I don't know if this will cause a high resource overhead due to spawning the player in very different locations

thorn isle
#

that looks like a purely random distribution, i.e. an uniform distribution yes

quaint basin
#

This is because in small ranges there is still a probability that 2 players are loading the same chunks but in different caves and thus mining different ores. But with very large ranges, it's the scenario where more chunks are loaded per tick in the world

thorn isle
#

i don't expect the distribution itself to have a large effect on performance; chunk loading is chunk loading no matter which order you do it in

quaint basin
thorn isle
#

if your validation fails, it may be cheaper to pick a position to retry with somewhere near the first, but i wouldn't this to be very significant

thorn isle
#

what i do in my rtp plugin is i have a whitelist of biomes i teleport players to

#

computing the biome of a location can be done from noise asynchronously, so the first validation step occurs entirely off of the main thread

#

from there iirc i take a chunk snapshot of the location and try to find a valid position within the snapshot

#

if there isn't one, i try elsewhere

quaint basin
thorn isle
#

well

#

do you want your players to teleport into an ocean?

#

no trees to chop there; bad start

quaint basin
thorn isle
#

that requires a chunk load, which must be sync, and is slow

quaint basin
#

A biome can contain water and not be of the ocean type

thorn isle
#

checking the biome from noise is orders of magnitude faster

#

yes, you still need to check for water

#

but checking the biome will reduce chunk loads by about half, considering about half of the world is oceans

thorn isle
quaint basin
#

never heard about noise

#

I'll see how I can do that

thorn isle
#

it's what minecraft generates its terrain from

ivory sleet
thorn isle
#

there should be a method on the World class for it

#

myeah, assertions do have their drawbacks

thorn isle
# thorn isle if there isn't one, i try elsewhere

the rtp positions are stored in a ring buffer ahead of time, so when a player requests to teleport, i can just pop one from the buffer and teleport them instantly, and then queue a new position to be found and added into the buffer asynchronously

#

this means i can be quite strict with my position validation without having to worry about players running into shit like "sorry, couldn't find a position to teleport to in time" like many other rtp plugins do

quaint basin
thorn isle
#

i think World::getBiome does it, i'm not 100%

wet breach
thorn isle
#

some of the biome methods return biomes computed from the noise, others from actual chunk data, and i don't know if it's even documented which does which

thorn isle
quaint basin
# thorn isle some of the biome methods return biomes computed from the noise, others from act...

/**
* Gets the {@link Biome} at the given coordinates.
*
* @param x X-coordinate of the block
* @param y Y-coordinate of the block
* @param z Z-coordinate of the block
* @return Biome at the given coordinates
* @see #getComputedBiome(int, int, int)
*/
@NotNull
Biome getBiome(int x, int y, int z);

// Paper start
/**
 * Gets the computed {@link Biome} at the given coordinates.
 *
 * <p>The computed Biome is the Biome as seen by clients for rendering
 * purposes and in the "F3" debug menu. This is computed by looking at the noise biome
 * at this and surrounding quarts and applying complex math operations.</p>
 *
 * <p>Most other Biome-related methods named getBiome, setBiome, and similar
 * operate on the "noise biome", which is stored per-quart, or in other words,
 * 1 Biome per 4x4x4 block region. This is how Biomes are currently generated and
 * stored on disk.</p>
 *
 * @param x X-coordinate of the block
 * @param y Y-coordinate of the block
 * @param z Z-coordinate of the block
 * @return Biome at the given coordinates
 */
@NotNull
Biome getComputedBiome(int x, int y, int z);
// Paper end

I don't know which one I should use.

thorn isle
#

honestly me either

#

This is computed by looking at the noise biome at this and surrounding quarts
this makes me think this is what you should use

#

The computed Biome is the Biome as seen by clients
this makes me think this isn't what you should use

ivory sleet
#

@quaint basin what version ru using?

quaint basin
ivory sleet
#

Ah ok

quaint basin
#

But you thought exactly what I thought

thorn isle
#

yeah that's why i'm conflicted

#

it says one thing and then another

#

i think what it means to say is it does read the biome from the chunk data, rather than noise, but uses the same interpolation as the client uses to determine where the possible biome borders between the quarts are

quaint basin
#

He seemed convincing to me

thorn isle
#

try World::getVanillaBiomeProvider

#

note that this approach doesn't work if you're using a world generator or a plugin that changes where biomes are after the world is generated

quaint basin
thorn isle
#

e.g. it won't work on most earth maps where the biome is part of the map data

quaint basin
#

But it seems so xd

thorn isle
#

there is noise that's used in world generation, and then there's noise used by the client to draw the biome borders after world generation

#

since the biome storage resolution in chunks is 4x4x4, using that data directly would make ugly straight lines

#

so what the client does is it adds some noise to that data so the borders twist and turn a bit at random

quaint basin
thorn isle
quaint basin
thorn isle
#

should exist on 1.21.8 as well

#

it's just on the WorldInfo interface which World extends

eternal oxide
#

Does not exist on Spigot

thorn isle
#

judging by the docs/sources he's looking at, he's on paper

quaint basin
#

yea im on paper

thorn isle
#

oh i maybe made a typo

quaint basin
#

now it is provider#getBiome?

thorn isle
#

also check the regular biomeProvider() and see if it's null i guess

#

myeah

quaint basin
#

eturn the Biome which should be present at the provided location.
Notes:
This method must be completely thread safe and able to handle multiple concurrent callers.
This method should only return biomes which are present in the list returned by getBiomes(WorldInfo)
This method should never return Biome.CUSTOM.
Params:
worldInfo – The world info of the world the biome will be used for
x – The X-coordinate from world origin
y – The Y-coordinate from world origin
z – The Z-coordinate from world origin
Returns:
Biome for the given location

#

why must lol

quaint basin
#

@NotNull BiomeProvider vanillaBiomeProvider();

thorn isle
#

i mean the regular biomeProvider()

#

world generators can set their own biome provider, which that will return if set

#

if not set, world gen falls back to the vanilla provider, which is always present

#

so we should do the same; prioritize the one set by the custom generator, or if not set, use the vanilla one

thorn isle
#

i.e. we require it to be thread safe

quaint basin
thorn isle
#

the notes are for the devs implementing the interface

#

telling them that they must make it thread safe

quaint basin
#

oh ok

thorn isle
#

because devs like us expect it to be thread safe

quaint basin
#

make sense now

quaint basin
eternal oxide
#

is teh getProvider marked as not null?

#

prfetty sure its never null

#

nope you are correct, it can be null

quaint basin
#

How can I obtain WorldInfo through World?

thorn isle
#

World extends WorldInfo

#

if you have a world, it is your worldinfo

wet breach
lavish wing
#

Guys, can someone help me with getting minecraft_server pom's? How can I get one by myself?

buoyant viper
#

huh

lavish wing
#

Without maven

buoyant viper
#

POM
without Maven

?

lavish wing
#

I mean, without bukkit/spigot maven

buoyant viper
#

u just want to download the vanilla minecraft server?

lavish wing
#

something like this

lavish wing
buoyant viper
#

until now yeah

#

u need to run some sort of tool to deobf otherwise, which would more or less mean running spigots BuildTools software

lavish wing
#

Is there's another way to compile it without BuildTools? I have 1.6.4 compiled minecraft_server POM's by my friend, but he forgot how he did it
Now I need to make 1.3.2 minecraft_server POMs

buoyant viper
#

ModCoderPack also exists for some older versions if u need to decompile or modify the client and/or server, but its mappings werent the greatest sometimes

#

idk about workin on anything earlier than 1.7 tbh

thorn isle
#

for the record pom is the build metadata file that maven uses to configure a project build, and isn't related to this

buoyant viper
#

if u just need an older (pre 1.8) server jar u could try scouring the umbral plane

#

or @wet breach probably has every build known to man

lavish wing
#

I found minecraft_server

#

md5 my beloved

fading drift
#

anyone knowledgeable on how hypixel server instances communicate to eachother

young knoll
#

Probably some messaging system

#

Like Redis

#

Or maybe they just do it via raw sockets ¯_(ツ)_/¯

thorn isle
#

redis does have messaging but it's a bit lacking

#

for dedicated messaging, i'd go with rabbitmq or something

wet breach
bleak plinth
#

hii so im making a Minecraft Server and have a discord but i need a Minecraft dev what u get with it? minecraft dev perms dev role
and a good community
i hope i can get a Dev in my discord team!

undone axleBOT
drowsy helm
#

chances of getting a dev for no money is slim

bleak plinth
#

maybe your right but i had an awsome 1 and he knew i was low on money but he enjoyed the team and the server so i dont think money is always needed

young knoll
#

Had?

#

Sounds like money is needed

bleak plinth
#

i was giving that guy money for the money services like donos

bleak plinth
#

working

#

but alright my excuses for doing this dumb things and asking for this

pastel peak
#

anyone able to help? i have a server that has items adder and i created a custom script using java to make a snowball have a knockback but the issue is that it only applies to mobs, it has no effect on players, im wondering if paper or spigot might have something that could be blocking the effect?

this is my code

package iascript;

import org.bukkit.event.Event;
import org.bukkit.plugin.Plugin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Snowball;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.inventory.ItemStack; // <-- Add this import

import dev.lone.itemsadder.api.CustomStack;
import dev.lone.itemsadder.api.scriptinginternal.ItemScript;

public class kb20 extends ItemScript {
@Override
public void handleEvent(Plugin plugin, Event event, Player player, CustomStack customStack, ItemStack itemStack) {
if (!(event instanceof ProjectileHitEvent)) return;

    ProjectileHitEvent e = (ProjectileHitEvent) event;
    Entity projectile = e.getEntity();

    // Check if projectile is a snowball
    if (!(projectile instanceof Snowball)) return;

    // Get the snowball's shooter
    if (!(projectile instanceof Snowball snowball)) return;
    if (!(snowball.getShooter() instanceof Player shooter)) return;

    Entity hitEntity = e.getHitEntity();

    if (hitEntity == null) return;

    // Calculate the direction from the shooter to the entity
    Vector direction = hitEntity.getLocation().toVector()
            .subtract(shooter.getLocation().toVector())
            .normalize()
            .multiply(20); // Adjust for strength

    // Apply the knockback
    hitEntity.setVelocity(direction);
}
young knoll
#

Probably too strong

#

The server doesn’t like players moving too quickly

fading drift
#

idk why this cant find it, but my other project can find it when I specify a library

#

I havent touched this in over a year, is there something I'm forgetting?

young knoll
#

spigot-api is just the api

#

If you want the server internals too just use spigot (and run buildtools for that version)

fading drift
#

I forgot what buildtools is

#

is there a guide somewhere

young knoll
#

?bt

undone axleBOT
fading drift
#

so am I correct in saying that to use server internals in code, I must provide a spigot jar

abstract fox
#

Hi, I'm having a problem with my Minecraft server. Sometimes I can't move my inventory. If anyone knows why this is happening, please let me know. I'd really appreciate it.

young knoll
fading drift
#

yeah sorry I just figured that out

#

so if I wanted to collaborate with others, they would either need to run buildtools themselves or I would supply the jar

sly topaz
#

supplying the jar sounds annoying given they'd have to put it at the right place

fading drift
#

not if I just have it in the git repo and use <dependency> <groupId>org.spigotmc</groupId> <artifactId>spigot-server</artifactId> <version>1.8.8-SNAPSHOT</version> <scope>system</scope> <systemPath>${basedir}/../../libs/spigot-1.8.8.jar</systemPath> </dependency>

eternal oxide
#

you need the non snapshot repository for the api, don't use system paths

#

?maven

undone axleBOT
azure escarp
#

Hi guys.

I am making a prison core for my server and wanted to ask smth related to the libs that amma start.

Text color utils
Config file loader
Command manager
Item builder
Simple GUI builder
Cooldown manager
Small event utilities
Database service (MySQL, Mongo)
Economy wrappers
Cache utilities
Json adapters
File utilities```

What else should I add in the Libs, never made Libs so idk what to add XD

Also the prison core is gona be like OPLegends/EMC etc
wet breach
#

you should limit the amount of libs

#

if you are making a core plugin, that core plugin should be primarily the lib to rely on to provide stuff. Therefore, the core itself you should limit the amount of outside libs it itself. Otherwise your core is at the wim of these libs or you are waiting on these libs to provides updates/fixes or when they do it throws everything you have out of whack. So, you really should limit to what you really need.

#

If all you are doing with these libs is just making use of a single feature or just a few methods, it would be wise then to just create your own feature/methods into the core of the plugin yourself. This also removes the amount of excess code your core ends up having or unnecessary stuff in general.

#

@azure escarp

quaint basin
#

If I do item = world.dropItemNaturally; Map.put(viewerUuid, item.getEntityId), can I intercept the SpawnEntityPacket and then, if the player's UUID from that packet is on that map and the entity ID of that packet is the value with the key of the player's UUID on the map, will cancel sending the packet to the client work? My fear is that the packet will be sent before Map.put.

chrome beacon
#

if it runs before or after depends entierly on where you call map.put

thorn isle
#

i dislike "core" plugins

#

and libraries

#

they tend to become an endless dumping ground for difficult-to-maintain garbage that then ends up dragging everything else down

#

if i had a cent for every plugin that'd died and was abandoned because the core it relied on became unmaintainable, i wouldn't be a millionaire, but i would have many cents

quaint basin
quaint basin
thorn isle
#

a way to get around this is to modify the map before adding the entity to the world

#

you can use the World::spawn method with Item.class, then in the Consumer<Item> which runs before the entity is added to the world, apply a random drop velocity to the item (this is all the dropItemNaturally method does), and put it into the map

#

i think it's at least in principle possible for the packet to get sent before the main thread gets to the map.put, but i don't remember if i've had that happen in practice

#

for reference, here is the actual impl of dropnaturally

    public Item dropItemNaturally(Location loc, ItemStack item, Consumer<? super Item> function) {
        Preconditions.checkArgument(loc != null, "Location cannot be null");
        Preconditions.checkArgument(item != null, "ItemStack cannot be null");
        double xs = Mth.nextDouble(this.world.random, -0.25, 0.25);
        double ys = Mth.nextDouble(this.world.random, -0.25, 0.25) - (double)EntityType.ITEM.getHeight() / 2.0;
        double zs = Mth.nextDouble(this.world.random, -0.25, 0.25);
        loc = loc.clone().add(xs, ys, zs);
        return this.dropItem(loc, item, function);
    }
#

however, it turns out that it has a consumer that's run before the entity is added to the world as well, so you can just call this instead of world::spawn

quaint basin
#

Yes, thank you

minor garnet
#

nmsPlayer.playerConnection.sendPacket(new PacketPlayOutCamera(cam));

im trying to make it so that when the player enters the view of an entity (like when spectating it), the entity keeps rotating its camera based on the
player's camera movement. However, iim not finding a way to detect the player's yaw and pitch while spectating. PacketPlayInFlying does not contain any yaw or pitch values. Is there any way to detect the player's camera rotation (yaw and pitch) in this situation?

thorn isle
#

i'm not certain if the client even sends any "look around" input in that state, since the client can't look around while spectating

#

you can get keypresses with the input event/packet, but i'm not sure about mouse input

chrome beacon
#

If you make the player ride on the entity it's currently spectating it should start sending movement packets

minor garnet
#

you can get keypresses with the input event/packet, but i'm not sure about mouse input

yeah i can do that

thorn isle
#

mmm i remember this trick

minor garnet
#

but camera rotation ?

thorn isle
#

i don't recall it being used to capture mouse input, but it could work if it actually sends proper movement packets

#

i'm just not sure if the player would just send the spectated entity's pitch/yaw or its deltas, since the screen is locked to those

#

worth a try at least; i do vaguely recall someone doing something like this before, so it might be possible

chrome beacon
#

^ I'd give it a try

#

Do let us know if works uwu

minor garnet
#

sre

quaint basin
thorn isle
#

Chunk::getSnapshot

#

do use the javadocs though

quaint basin
#

oh nvm

#

But what should I use this for?

thorn isle
#

it's an immutable and thread-safe snapshot of the chunk's state

#

use it to find a valid position to place the player in within that chunk

quaint basin
#

between the time I receive the snapshot and the tp

thorn isle
#

this way you're not bogging down the main thread with your checks

#

that is highly improbable; but i suppose if you really want to avoid that, load the chunk before the tp and verify that the space isn't occupied, and pop another location from the buffer if it is

young knoll
#

The overhead of taking a chunk snapshot probably isn’t worth saving the overhead of getting the highest block at a location

thorn isle
#

if your checks are very simple, like just finding the topmost block in a column using the heightmaps, and making sure the block is safe to teleport on, you can forgo the chunk snapshot

#

i do relatively complex checks, so rather than loading another chunk if the checks fail, i go through multiple positions within the chunk asynchronously

thorn isle
#

that the position is valid

quaint basin
thorn isle
#

you don't want to teleport the player into a lava lake or at the bottom of a ravine

#

i also avoid placing the player on top of trees, searching underneath foliage instead

quaint basin
#

The tallest block in the world will never be under a cave

thorn isle
#

cave != ravine

quaint basin
#

i need that too

#

xd

thorn isle
#

the upside of taking a snapshot is that you are much more likely to find a valid position somewhere in the chunk and won't have to load another chunk

quaint basin
#

Is your code public?

young knoll
#

Shoutout to the MOTION_BLOCKING_NO_LEAVES heightmap

thorn isle
#

no

quaint basin
young knoll
#

Sadly you could get unlucky and end up picking the column with the tree trunk in it

thorn isle
#

records the highest position with a block in a block column, ignoring leaves

young knoll
#

A block that has collision

quaint basin
thorn isle
#

chunk snapshot has getHighesBlock(Heightmap) or something

#

so does chunk

#

world maybe too

quaint basin
thorn isle
#

on the snapshot, yes

#

on anything else, no

#

hence taking the snapshot

quaint basin
#

the problem with this is a player placing a block meanwhile

young knoll
#

I think you technically can read the world async

thorn isle
#

you can, and it's actually quite safe and performant on paper

quaint basin
thorn isle
#

on spigot i think it will just schedule a task that wraps the get to run at the start of the next tick, so you'll impose a latency up to 50ms

quaint basin
young knoll
#

Well if it does schedule a runnable a chunk snapshot will allow you to do everything in the same tick

#

Instead of check -> wait -> check again -> wait -> etc

quaint basin
thorn isle
#

just use the javadocs

#

all the methods are there

#

open the chunksnapshot page and ctrl-f height or something, or just read the methods

#

i'm not a search engine

quaint basin
quaint basin
quaint basin
thorn isle
#

i do, and i know it's there

quaint basin
#

and doesnt have anythin about heightmap

thorn isle
#

but i'm not 100% about the name

young knoll
#

Yeah wtf vcs2 you don’t know every spigot method signature off the top of your head?

quaint basin
thorn isle
#

despair

#

okay upon further inspection of the javadocs, it seems like the chunksnapshot is actually ass and forces you to use a specific heightmap type

quaint basin
thorn isle
#

the data for all the heightmaps is recorded on it, but there's only api for querying the "highest taken" one

thorn isle
#

in the off chance that they are, you can tell the player to try again later

quaint basin
thorn isle
#

you'd need like 300 players to use the command within a few seconds to run it dry

quaint basin
#

I'm not understanding anything 😭

thorn isle
#

put a reasonable cooldown on using the command and it shouldn't be a problem

quaint basin
thorn isle
#

serverwide

#

or no, worldwide; or whatever other domain you want, but worldwide makes the most sense

#

every position in the buffer should be interchangeable

thorn isle
#

so if you want to rtp in the nether, you pop a position from the nether world's buffer

quaint basin
#

I'm not going to have a buffer of enormous size

thorn isle
#

it can be 30 million by 30 million, it doesn't matter

quaint basin
thorn isle
#

no

#

the buffer is a list of pre-calculated safe rtp destinations

#

it's called a buffer because it bufers the output of the producer thread (finding the safe positions) and the consumer thread (teleporting players to them on demand)

#

it allows you to dispatch teleportations instantly rather than have players wait until you find a position for them

quaint basin
thorn isle
#

and once you do, you pop it from the buffer and tell the producer to find a new safe destination to put in the buffer

#

no

#

it can be any size you want, depending on how many rtp positions you think you'll need to "burst" through

young knoll
#

Make it dynamic :p

thorn isle
#

e.g. if you have 100 concurrent players and you expect they might all decide to run /rtp at the same time, your buffer should be 100 positions long

young knoll
#

If it ever gets down to 0 increase the capacity by 10 or something

thorn isle
#

at startup, and then topped up as needed

#

in principle you could persist it so you don't need to recompute it at startup, but in practice that's not worth the effort

quaint basin
thorn isle
#

this isn't c, you don't have to reallocate it manually if you have to resize it

#

or are you intending to ask when you should refill it?

quaint basin
young knoll
#

You hold a list of valid teleport locations

#

If its size is < howManyYouWantToHaveBuffered then you calculate a new one

quaint basin
#

From what I understand, you're telling me to have a list of safe locations in the startup, but these safe locations will eventually run out, so I'll have to add more safe locations but I don't know when, and to my liking, this is just complicating the basics because I don't understand anything

quaint basin
#

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

thorn isle
#

despair

#

you hold the list forever

#

when you use a location, you remove it from the list

#

when the list becomes too small, you add new ones to the list

thorn isle
#

okay

#

conceptualize this

#

you have a fridge

#

yes?

quaint basin
#

yes

thorn isle
#

the fridge has food in it

quaint basin
#

no

thorn isle
#

what happens when you get hungry?

#

you take something out of the fridge and eat it

quaint basin
#

I'm going to have dinner soon

thorn isle
#

now the fridge has less food in it, yes?

quaint basin
#

yes

thorn isle
#

so at some point you look at the fridge and go "hm, i don't have much food left"

#

and at that point you go to the grocery store to get more food

#

and you put it in the fridge

#

the fridge is your buffer

#

the food is teleport locations

quaint basin
thorn isle
#

the grocery store is the position finding algorithm

#

yes, that's what "at startup" means

young knoll
#

You create it at startup

thorn isle
#

and as the list over time shrinks, you add more positions in it so you don't run out

young knoll
#

You fill it over time, as needed

quaint basin
#

Having this list doesn't make sense because 10 seconds later all those locations on that list could be unsafe locations

thorn isle
young knoll
#

You could actually have the producer be its entire own thread as long as you use a thread safe list and make use of BukkitSchedular#callSyncMethod to get your chunk snapshot

quaint basin
# thorn isle

This is unlikely, but I want to avoid it, but I think you're complicating things

thorn isle
#

this is what i do, i have a BlockingArrayQueue and a thread blocking on add on it; it'll run whenever there's space

young knoll
#

Well if you want to do it the way extreme lazy way

#

Just teleport the player way above the surface and give them slow falling for a bit

#

That pretty much means you only need to check you aren’t teleporting them into an ocean

thorn isle
#

if this is your first plugin and the concept of a buffer is difficult for you, you can just do the lazy thing and tell the player "you will be teleported soon" when they run the command

#

and find the destination in real time, and teleport as soon as you find it

quaint basin
quaint basin
thorn isle
#

okay now you are just clowning on him

young knoll
#

Slow falling

#

So they don’t take fall damage and can steer themselves away from lava or ravines or whatever

quaint basin
#

Based on this code, do you think this is my first plugin?

thorn isle
#

brother i have been trying to explain to you what a buffer is for the past half an hour

quaint basin
#

I know what a buffer is; you're the one who doesn't understand my question

#

There's clearly a simpler way to do this than what you're talking about

young knoll
#

And unless you have a really bad algorithm for finding a safe location or the player is really unlucky

#

It won’t take that long

quaint basin
young knoll
#

Sure

quaint basin
young knoll
#

Means you can teleport them instantly

#

And never have the command fail

quaint basin
young knoll
#

There should always be safe locations in the buffer

#

If there aren’t, you need a bigger buffer

quaint basin
young knoll
#

Like I said, the buffer should never get empty

#

If it does that means you should make it bigger

quaint basin
young knoll
mortal hare
wet breach
#

to blow your mind that not everything has to run in the server

sly topaz
buoyant viper
#

IPC go brrr

wet breach
sly topaz
wet breach
sly topaz
#

is this for a minigame? If that's the case then yeah

wet breach
#

what is stopping generating a survival world?

#

not understanding here

sly topaz
#

compute lol

wet breach
#

compute?

sly topaz
#

pregenerating a world can take weeks if the range is big enough

wet breach
#

no

#

only takes hours

#

unless you have a potatoe

sly topaz
#

it definitely does not, and besides file size is a concern too

wet breach
#

why is that a concern?

#

we have terrabyte drives.....which MC is not going to fill up

#

10milx10mil generated world without doing anything takes up like 10GB and it takes something like 3-4 hours to generate

sly topaz
#

takes about 17gb if no nether and end, and probably more like 12 hours

wet breach
#

not sure what you are using that it takes so long for you o.O

sly topaz
wet breach
#

what do you mean scales pretty badly? Every region file is going to be relatively the same size

#

if we are not factoring in any modifications being done

sly topaz
#

just take a look at the calculator as you increase the radius, it is pretty insane

#

and you can check pretty much any chunky guide about how much time it takes, they warn people about it possibly taking a day if not multiple days

wet breach
#

50k blocks is not 500gb

sly topaz
#

it is radius

#

would be 50x50k

wet breach
#

yeah obviously wrong

sly topaz
#

it isn't though

wet breach
#

but it is because most of your world is air blocks

#

sorry, there is not 500gb worth of data in 50k by 50k

sly topaz
#

you can pregenerate a world with chunky and see for yourself

#

we are not in 1.8 anymore where the worlds wouldn't go past 100gb

wet breach
#

even setting it to 1.8 that site says there is 200gb+ in 50k by 50k

#

so yeah, not trusting it. Obviously whatever math it is using is very flawed

sly topaz
#

your perception of how big worlds usually are is just wrong

wet breach
#

its not. ran servers before. In terms of amount of storage space minecraft worlds are small

sly topaz
#

most servers won't pregenerate past 10-20k radius, since that's plenty for a survival for a few years

wet breach
#

I have always done 10mil by 10mil

sly topaz
#

yes, and that would be around 10gb

#

it just scales really badly

wet breach
#

there is no way that if 10mil by 10 mil is 10gb, that 50k by 50k would be significantly larger

sly topaz
wet breach
#

no

sly topaz
#

again, if you don't believe it then go pregenerate a world, see how much it takes and what size you end up with

wet breach
#

it averaged out to 10gb. IT could be larger now, but there is no way from 1.8 to 1.21 that the same dimensions would be an order of magnitude of 50 times larger in space

#

when ever I feel like setting up a server I will. on pc that size will take a while, but on a server box it takes only a few hours

sly topaz
#

10x10, probably about 12 hours using spigot, that's at least how much it took me last time I did it (in 1.21.5)

wet breach
#

10x10? as in 10k or 10mil?

sly topaz
#

10k radius

#

wait, you were talking about millions? Lol

#

because radius in the millons take weeks

wet breach
#

radius in the millions is not slower then a cube

#

cube is larger then a circle =/

strong forge
#

that site provides a very accurate estimate for world size, it's been sampled over hundreds of worlds from the guy that created it

#

it's kind of ignorant to just write it off as "the math must be wrong" when you can literally just test it once and see immediately that it's correct

silent river
#

Just from a mathematical standpoint: Disregarding the Y-axis, radius means that from an origin, assuming a square, it extends out by radius blocks in each direction. So 10 blocks radius results in a 20x20 square. Adding together those results in 400.

Let's do the same for 10k (5k rad): 10,000 * 10,000 = 100,000,000.
Again for 20k (10k rad): 20,000 * 20,000 = 400,000,000.

As you can see, a 2x increase in radius results in a 4x increase in the amount of blocks that need to be generated (this is the same case in chunks btw; you'd simply divide the radius by 16 and the result by 256). This means shit scales fast.

Let's do the same calculation for 10 million:
10,000,000 * 10,000,000 = 100,000,000,000,000

That's a ton of blocks, don't you think? And you suggest that you can put 100 trillion columns of blocks in just 10 gigabytes of data? You must be insane.

solid cargo
#

Yep, same thing is 3d printing actually. When you increase your model size by 10%, the time to print doesnt increase by 10%, instead its closer to 30% ish

silent river
#

Well, it increases by 10% cubed, which is about 33.1%

solid cargo
#

Yes, thus ish

#

Anyways the point stands, the increase is not linear

ivory sleet
#

ig u get 10^2 also if ud consider height

#

so 10^16 blocks in 10^10 bytes

smoky anchor
#

compression babyyy

ivory sleet
#

and all that in 4h

wet breach
#

air blocks don't take up space like you think it does

smoky anchor
#

That sounds wrong
MC does have some optimizations for single block sub-chunks, is that what you mean ?

silent river
#

And in average about 80 blocks per column is not air

#

What's your point

#

Actually more than 80, it extends in the negative Y as well

smoky anchor
#

was it full or subchunks that have this
I don't remember exactly

wet breach
#

air blocks don't take up space

strong forge
#

generate a world and then come back

wet breach
#

I have over the years.....I am not going to generate one now on my pc as it does take longer on a pc then it does on a server box

strong forge
#

then stop spreading misinformation

wet breach
#

you guys act like I am new to MC or something

silent river
#

real

#

you seem to be

strong forge
#

you sound like it with how you understand world gen lol

smoky anchor
#

How can air "not take up space"
It is the same as a normal block in a block-mixed chunk
there has to be some "x of air blocks" information
I'll just pull up the chunk spec

strong forge
#

air compresses rather well but it doesn't take up "zero space"

silent river
#

And chunks also don't consist purely of air lol

wet breach
#

air blocks take up no space, you can go look to see how blocks are stored

silent river
#

They have a rather big amount of non-air blocks too

silent river
#

Please

strong forge
#

yeah i know how they're stored because I've written tools for this lol

wet breach
silent river
#

You pretty clearly aren't

wet breach
#

alright, show me where air is taking up space?

strong forge
#

either way just to stop derailing the original topic, the onlinemo.de site is very accurate for world sizes, and that is accounting for the air blocks

#

go generate a real world and you can easily confirm it's correct

#

no need to argue over nothing here lol

smoky anchor
#

I have started generating a world with Chunky
10k x 10k
20% there, will take like 4 more hours
So far at 3GB I think

wet breach
#

what are the 0's? never used chunky

smoky anchor
#

x y for center to generate around

wet breach
#

ah

strong forge
#

technically 20k x 20k then but that should be about 16-17gb according to onlinemo.de

smoky anchor
#

ye 10k radius

strong forge
#

sounds about right from your 20%

wet breach
#

hmmm....seems I am going to have to manually update WorldBorder

tacit thistle
#

You can just calculate how many chunks would be in 10mil*10mil and, as you are quite familiar with the anvil format, use one sector per generated chunk as a lower bound

smoky anchor
#

Ended the little experiment to stop torturing my PC
31% and I have 4.5GB world

quaint basin
#

Soon you'll be telling me to have a process to set the player's life, kill the player, kick them out, etc.

#

1001 processes 😎

wet breach
#

no on that last part, and not sure where you get enormous processing load from as well

#

anyways, it really depends on what exactly you want it to do

#

the reason an external process would be faster other then most likely being on a different core from the server is that its just a smaller program overall therefore its loop cycle is a lot faster then that of the servers. So even if it did have to process a lot, it would still be a faster cycle

young knoll
#

I mean

#

You’d still need the server to generate the chunks

#

Assuming everything isn’t pregenerated

wet breach
#

right, if its not pregenerated

thorn isle
#

The other advantage of a buffer is that you avoid spikes in cpu load by being able to distribute the workload over time

#

100 players running /rtp at once will make the server shit bricks if it's already under load

#

With a buffer, it just means a lightweight background process is going to run for some amount of time until the buffer is refilled

#

The compute used is the same, but it's spread out

ivory sleet
#

Tbh dating back to the original problem, you can also just rate limit rtp on an individual (w a cooldown) and a collective level (not allowing more than x rtp requests per tick), more so if u dont want to buffer, there's probably no harm in letting the player at hand wait a little bit whilst the server is fetching a safe location?

onyx fjord
#

does Bukkit#getPlayer(name) just ignore case or something else ?

wet breach
worldly ingot
#

It actually does matching if I'm not mistaken

#

Like if I were to do Bukkit.getPlayer("2008") it would return my player despite the username being "2008Choco". It searches for names that start with the input string and returns the one that's closest

#

Bukkit#getPlayerExact() doesn't do matching and requires an exact match username. #getPlayer() checks for exact matches first

hybrid spoke
#

so it's case insensitive, but it may not return the player wanted if you're not precise enough

worldly ingot
#

Correct

wet breach
#

well, I was partially right then lol

#

Yay for choco with knowing the exact thing

quaint mantle
#

nerd

worldly ingot
#

10 years of being around Bukkit does that to a guy

umbral ridge
#

hey

#

this is the new locator bar, is it possible to create these points? in the code?

smoky anchor
#

iirc an entity has to be present
you give it the waypoint something attribute and it shows
I don't remember how but you can retexture the points with custom RP

thorn isle
#

i don't recall there being api to directly create them (though the protocol does support that, even without an attached entity), but you can use the attribute api to make entities have them

#

basically the protocol just sends some (uuid, x,y,z, icon id) packet for each

umbral ridge
#

oh so the point is an entity like an npc

#

alright. btw is locator bar always visible? because its invisible right now, in an empty world. my guess is that it only appears if a point or more is/are present?

smoky anchor
#

I believe only when a point is in the fov of the thing

#

otherwise it switches back to XP

#

it also switches to XP when the XP changes

thorn isle
#

rather than fov i think it's tied to range

#

though i'm not 100%

umbral ridge
#

complicated stuff

#

its complicated to spawn it and then you have to do all kinds of stuff which would probably take me a few hours to figure it out and polish... not worth it

#

you have to have an entity, then that entity has to have an uuid, then if its an entity, you can attact an attribute to it, but thats just a mess with command blocks.. meh

#

and on top of that, that only works for singleplayer world. not local server kind of thing

smoky anchor
#

"then that entity has to have an uuid"
I find this very funny, every entity has a uuid whether you like it or not lol

thorn isle
#

i don't get why there's no proper api for it

#

the protocol supports just sending waypoints directly to the client, no entities involved

#

there should just be a Player::addWaypoint(UUID, Location, Icon) or something

sullen marlin
#

Maybe you could PR it

pseudo hazel
#

spigot is clearly understaffed

#

xD

golden turret
#

how do i create a player head based on the texture url?

#

nvm, found it

#
                PlayerProfile profile = Bukkit.createProfile(UUID.nameUUIDFromBytes(url.getBytes()));
                PlayerTextures textures = profile.getTextures();
                textures.setSkin(URI.create(url).toURL());
                profile.setTextures(textures);
                meta.setPlayerProfile(profile);
noble saddle
#

Hello is there a way to get the string of a chat message that was created by console via command?
data get entity @e[type=minecraft:zombie,limit=1]
Outputs a string a chat that I want. I tried all of the chat events, none captured it.

young knoll
#

You’d have to use some sort of system to intercept logging

#

But this seems like

#

?xy

undone axleBOT
noble saddle
#

yes it is lol

#

Im trying to get nbt of an entity

#

but I want to avoid using the NBT API

young knoll
#

What NBT do you want

noble saddle
#

Theres a way to intercept logging with bukkit? Like through an event?

young knoll
#

Pretty much all of it should be available through api methods

noble saddle
#

literally an entity's entire NBT

#

huh ok

young knoll
#

getHealth for health, getEquipment for armor and held items, etc

noble saddle
#

oh right, I was doing that at first which was fine, but the shear amount .... it was getting too much

#

I just thought its gonna be faster if I can somehow obtain the NBT

young knoll
#

What do you want to do with it

noble saddle
#

duplicate an entity. copy its exact current state at a specific tick and duplicate it at a later point.

young knoll
#

Version?

noble saddle
#

latest

young knoll
#

Entity#copy(location)

#

Or Entity#createSnapshot

noble saddle
#

👀

#

Ill try that ty

#

wow it worked thanks!

native gale
#

Does anyone have a clue how to correctly encode or decode this field? The protocol description on the wiki is a bit confusing. I've been lurking on GitHub since yesterday looking for an example, because surely I'm not the first person on the planet who has attempted that, but I didn't find anything particularly useful. My goal is to reach and modify paletted containers in the chunk sections

sullen marlin
#

Presumably it's just a varint plus bytes?

#

What does the link say

native gale
thorn isle
#

best to check the chunk packet data encoding/decoding methods and just do what those do if you can't make sense of the wiki description

#

off the top of my head, all that field is is a list of serialized chunk sections

#

which themselves are just serialized palettedcontainers

#

if you have access to nms, you can delegate encoding/decoding directly to nms code

#

otherwise you'll have to put a decent bit of shoulder grease into it, since there are several different types of palette strategies, registries are involved, and you have the whole "block nibbles in longs" logic from the container itself to deal with

#
       int chunkSectionIndex = 0;
        LevelChunkSection[] var4 = chunk.getSections();
        int var5 = var4.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            LevelChunkSection levelChunkSection = var4[var6];
            levelChunkSection.write(buffer, chunkPacketInfo, chunkSectionIndex);
            ++chunkSectionIndex;
        }

buffer here being a FriendlyByteBuf where the data goes

#

ignore chunkPacketInfo and i think also chunkSectionIndex, those are paper antixray nonsense

#

LevelChunkSection::write is very simple as well

    public void write(FriendlyByteBuf buffer, ChunkPacketInfo<BlockState> chunkPacketInfo, int chunkSectionIndex) {
        buffer.writeShort(this.nonEmptyBlockCount);
        this.states.write(buffer, chunkPacketInfo, chunkSectionIndex);
        this.biomes.write(buffer, (ChunkPacketInfo)null, chunkSectionIndex);
    }
#

states and biomes both being PalettedContainers, for BlockState and Biome respectively

#

palettedcontainer write directly delegates to PalettedContainer.Data::write

#
        public void write(FriendlyByteBuf buffer, @javax.annotation.Nullable ChunkPacketInfo<T> chunkPacketInfo, int chunkSectionIndex) {
            buffer.writeByte(this.storage.getBits());
            this.palette.write(buffer);
            if (chunkPacketInfo != null) {
                chunkPacketInfo.setBits(chunkSectionIndex, this.configuration.bits());
                chunkPacketInfo.setPalette(chunkSectionIndex, this.palette);
                chunkPacketInfo.setIndex(chunkSectionIndex, buffer.writerIndex());
            }

            buffer.writeFixedSizeLongArray(this.storage.getRaw());
        }
#

again ignore chunkpacketinfo, that's antixray nonsense

#

what this does is write first the palette and then the raw long[] of the data itself into the buffer

#

this is the part where it gets kind of nasty, because there are 4 implementations of palette

#

i'd really recommend some library or just straight up using nms instead of rawdogging it if you have to go this deep into it

young knoll
#

Just be lazy and always use the fancy palette

#

Kek

little canyon
#

Can someone help me with the protection stones pre 1.13 plugin?
I want it to:

  • prevent the actionbar error from appearing
  • remove protection from inventory when placed in creative mode

DM for more info

native gale
#

Sadly, .read() is not a static method. I need an already existing instance of LevelChunkSection to decode the buffer, and I can't figure out where to get the parameters needed for its constructor

thorn isle
#

public LevelChunkSection(Registry<Biome> biomeRegistry, Level level, ChunkPos chunkPos, int chunkSectionY)

#

i assume you're having trouble finding the biome registry?

native gale
#

Yes, as well as Level

thorn isle
#

level is just the handle of a bukkit world

#

((CraftWorld)world).getHandle()

#

it'll be a ServerLevel in particular

#

for the registry, uh

#

i never remember where their repository is, let me see

#

it used to be in BuiltInRegistries but ever since they became network synchronized they were moved into some dynamic registry nonsense

#

you have to use the ResourceKey<Biome> from nms.Registries to retrieve the registry from somewhere

#

possibly the registry registry

native gale
#

Uh...

thorn isle
#

alternatively

#

this is a bit of a hack, but you can get an existing chunk in the world of interest, and just get the biome registry it references

#

it's a public field on ChunkAccess which is the supertype of e.g. LevelChunk, which is the "handle" of bukkit Chunk

native gale
native gale
thorn isle
#

you only need to get it once per world per session

native gale
thorn isle
#

ResourceKey[minecraft:root / minecraft:worldgen/biome]
this is the ResourceKey<Biome> in nms Registries

#

Registries.BIOME specifically

#

it's a key into the registry registry

#

i assume you can get the biome registry itself using the key with BuiltinRegistries.REGISTRY.get(Registries.BIOME) or something along those lines, but with the generics involved it's difficult to say for sure without trying it out

#

choco or md or others probably know better, but if they don't spontaneously manifest with an answer, going with the hack of grabbing it from a chunk should work as well

native gale
native gale
thorn isle
#

those are the palette of the paletted container

#

basically the way the container works is that, rather than using a fullwidth reference to a value in the blockstate registry, which would be 4 bytes on most systems, it has a smaller palette that it references instead

#

if there are, say, <=16 different blockstates in a chunk section, the palette will only have 16 entries; and each blockstate reference can be represented with 4 bits, since 2^4 == 16

#

so to make sense of those references, the client also has to be sent the palette being referenced

little canyon
#

Can someone help me with the protection stones pre 1.13 plugin?
I want it to:

  • prevent the actionbar error from appearing
  • remove protection from inventory when placed in creative mode

DM for more info

thorn isle
#

i assume you're trying to implement this yourself?

native gale
#

No, I'll use the hack you suggested

#

Oh, you're not talking to me, sorry

thorn isle
#

just trying to determine whether i should clown emote him or not

tranquil pecan
#

should i use a global task to check if a player holds an item for 5 sec or per player?

(Just making a Lobby PvP plugin)

thorn isle
#

the bukkit scheduler isn't very good

#

if there's something you have to do every x seconds for y targets, where x is a constant and y is variable, it's better to have one task iterate over y rather than have y tasks in the scheduler with one target

tranquil pecan
#

okay

tranquil pecan
thorn isle
#

for asynchronous tasks, yes; for main thread tasks, no, you're stuck with the bukkit scheduler

native gale
#

For async tasks I usually use normal JVM async primitives, and when I need to feed the results back into Bukkit in the end, I schedule a synchronous task inside of async env

#

I believe it is the intended purpose of scheduling a task without delay

umbral ridge
#

whats the easiest way to copy/place blocks (predefined set of blocks) with code?
I was thinking of placing the existing structure somewhere innaccessible to a player, and then once I need that structure, I would copy each blocks and apply its rotation data etc.. to a new location.

#

if I have a small house, eg.: 15x15x15... would it take long to copy/paste with code?

#

i need it to be efficient, but at the same time, I don't want to use worldedit, because it would be kinda stupid to use it just for.. that. I won't need worldedit once the server is in production

young knoll
#

Why not just use the structure api

#

It’s like schematics but vanilla

umbral ridge
#

Hmm.. I wasn't aware of it :D .. can you give me a class name?

young knoll
#

Structure

umbral ridge
young knoll
#

Just make sure it’s the right structure class… there’s like 3

umbral ridge
#

this requires me to do a whole lot of things

young knoll
#

Not that one

#

The one in org.bukkit.structure

umbral ridge
#

How do I use this

#

this doesnt take any kind of blocks set

#

Ill probably have to do it myself... this seems like its over engineered for me

young knoll
#

It can be loaded from a file

#

Or from a point in the world

umbral ridge
#

But it doesn't take a file anywhere

young knoll
#

StructureManager

umbral ridge
#

ohh I see, so Structure can be a schematic?

young knoll
#

It’s an NBT file

#

Not the same format as a schematic

umbral ridge
#

how do you create one? if I build a house and want to save it as NBT

young knoll
#

But FAWE can save your selection as a structure file (I don’t think normal worldedit can)

#

Or you use the structure block in game

umbral ridge
#

with the structure file, are entities and all of the rotation data saved too?

#

eg. paintings, armor stands

young knoll
#

Yes

umbral ridge
#

perfect

#

so I have to first load litematic files and then save them as nbt, too much work 😿

young knoll
#

Might exist a converter somewhere

slender elbow
#

yes, it's called Minecraft

#

load it up, save it as a structure :^)

umbral ridge
#

ill save you as a structure emily

tight cliff
#

PersistentDataContainer is just a part of nbt under minecraft:custom_data right?
and bukkit or spigot can read write that data by PersistentDataContainer.
Then why does it not have a way to use nbt data directly?
It's already doing it in PDC isn't it?
I know I'm miss understanding how it works so please teach me where and why I'm wrong.

smoky anchor
#

You can't really use NBT directly. It's save data.
To get the NBT of an entity or something you need to save it, do modifications there and then load it again.
Which would be stupidly slow if you want to do many changes on many entities. For example just setting health.
You have API methods for that, they directly modify the value on the object, no saving/loading.

#

And NBT can change at mojangs will, for example Health -> health
If that were to happen, your plugin will stop functioning. You use the API that is (somewhat) stable and won't break as easily.

#

anyone, feel free to correct anything :)

tight cliff
#

I think I got it.
It's logically possible but not stable so api don't give access directly.
Thank you for detailed reply.

next plume
#

Any guesses why using Maven jar plugin version 3.5.0 causes the following error on pom.xml line 1 (the <project> line), while Maven jar plugin version 3.4.2 works just fine?

Cannot access Key[type=org.apache.maven.project.MavenProject, annotation=[none]] outside of a scoping block

native gale
#

Thank you, if I ever publish this plugin I'll credit you

thorn isle
#

💪

wet breach
#

To compile?

sullen marlin
#

Probably to set manifest entries

wet breach
#

that makes sense

#

but couldn't you use maven compiler to set those instead?

worn ridge
#

I am looking for a development team to write my own-our AC for the spigot-paper core on versions 1.16.5-1.21.8. I need a team with 6-8 people with about 2-3 years of experience in developing spigot-paper plugins. Maybe you're the right person for us!
Link:
Telegram WalendRuby
Discord walendru

eternal oxide
#

?services

undone axleBOT
native gale
#

I wonder... Is there a way to make BEES blow up like creepers?

#

We can spawn an explosion of course, but what about telegraphing to player that a bee is about to explode, hm

pseudo hazel
#

maybe you can make like a fuse effect with particles

#

and a sound

young knoll
#

You could make it grow with the scale attribute

smoky anchor
#

obligatory: probably core shaders for the visual effect

slender elbow
#

i would add a giant text display next to the bee that reads "this bee is about to explode"

hybrid spoke
#

make it shoot small honey blocks into all directions when it explodes which stick to the surroundings

alpine solar
#
        Objects.requireNonNull(getCommand("spawn")).setExecutor(new SpawnCommand(worldTeleportManager));

Is this required

#

or can I just do it without .requireNonNull

eternal oxide
#

You can do without. All it does is quiet an IDE warnign about a possible null

thorn isle
#

it changes nothing in terms of program behavior

#

but it does mean that when another dev looks at your code later, they'll know that you're aware of the static nullability but expect it to never be null in practice

young knoll
#

// This will never be null unless someone fucks up the plugin.yml

#

Can’t have that extra method call adding 2 microseconds to my server startup time

thorn isle
#

🤡 who cares about the warning anyway, half of my entire codebase is highlighted in yellow because everything paper has added since 2015 is "experimental and unstable"

slender elbow
#

lmao even

#

ijbol

umbral ridge
#

not only that its off center. no spacing, padding, margin, its colored, and its ugly

#

and it doesn't add anything to the text

#

no practical value

eternal night
#

Run it in-game and hover over it

slender elbow
#

are you implying that it does have practical value ?!?!

eternal night
sacred mountain
#

anyone want to help brainstorm ideas for objectives and secrets in an adventure map i'm making? Will be using a plugin and not just vanilla, though most of it is redstone and command blocks so far, so preferably a competent developer or builder with a decent amount of experience.

#

another question, can i force load the persistent data of an offline player? When i use the reset command for the map, each player has map objective keys to make sure the plugin knows what they have completed

umbral ridge
#

huh

#

if you hit a villager their trades go up, they get more expensive lol

young knoll
#

Yes

elder lichen
#

Hello, I need someone who knows how to make fakeplayer tablists, 4 columns, 20 rows each, version 1.21.8

elder lichen
# drowsy helm Yep whats the question

The question is that I made my code but it doesn't work on Spigot Paper, it runs but there is also an error and I'm looking for someone who knows how to do it from a to

thorn isle
#

not the place for that

#

but you can send the error and your code and perhaps someone will offer guidance for free

elder lichen
thorn isle
#

also remember to include the error if you are getting one

young knoll
#

What’s a Spigot Paper

#

Is that like a Mac Windows

winged scaffold
#

anyone need a minecraft dev reach out to me

young knoll
#

?services

undone axleBOT
tranquil pecan
wraith delta
onyx fjord
#

It's good for finding obvious errors in code

finite vapor
#

Hello,
I want to make a message appear when a player interact with a iron hoe, but it seem to not be working when i right click air or block (1.18)

Thanks in advance,

public class HoeEvents implements Listener
{
    
    private QuakeCraft QuakeCraft;
    
    public HoeEvents(QuakeCraft quakeCraft)
    {
        this.QuakeCraft = quakeCraft;
    }
    
    @EventHandler
    public void onInteract(PlayerInteractEvent event) 
    {    
        Player player =event.getPlayer();
        Action action = event.getAction();
        ItemStack item = event.getItem();
        
        if(item == null) 
            return;
        
        if(item.getType() == Material.IRON_HOE && (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK))
        {
            player.sendMessage("clique");
        }

    }

}
drowsy helm
#

code looks fine

finite vapor
#
public class QuakeCraft extends JavaPlugin{
    
    @Override
    public void onEnable()
    {
        Bukkit.getLogger().info("Quake actif!");
        
        new HoeEvents(this);
        new BlockEvents(this);
    }
    
    @Override
    public void onDisable()
    {
        Bukkit.getLogger().info("Quake non actif!");
    }

}
smoky anchor
#

That's not how you register listeners

drowsy helm
#

look at 1.4

#

    getServer().getPluginManager().registerEvents(new MyListener(), this);
finite vapor
#

alright thanks i'll try

drowsy helm
#

Bukkit needs to know the listener exists, if not it will just sit there

finite vapor
#

so this getServer().getPluginManager().registerEvents(new HoeEvents(this), this);?

finite vapor
#

it work

drowsy helm
#

🙂

glad jacinth
#

Any way to change the opacity of particles, plugin or texturepack?

onyx fjord
#

shader/resourcepack

prisma osprey
#

guys so how would i make that you get a string (item type) from a config.yml and it takes that string and turns it into a material to be used in like inventories and stuff

summer scroll
young knoll
#

Material.matchMaterial

prisma osprey
#

aight thank y'all ill try that rn

outer ember
#

There is something wrong with my block displays
when it goes into a block
it turns to BLACK
it's seems normal
but it destorys everything
i dont want it
what should i do

thorn isle
#

set its light level/brightness manually

#

an entity inherits its light level from the location it is in, and solid blocks always have a light level of 0, since light cannot go into them

#

so if you place a block over a display entity, it will appear dark

outer ember
young knoll
#

There isn’t a “default”

#

It depends on where it is

outer ember
thorn isle
#

15 sky 15 block

outer ember
thorn isle
#

Have you tried setBrightness?

outer ember
#

Yeah that works
ty

slender elbow
#

sob

pale lava
#

some of the versiions from BuildTool build/compile the wrong version.

"java -jar BuildTools.jar --rev 1.20.5" installs 1.20.6
"java -jar BuildTools.jar --rev 1.21.2" installs 1.21.3
"java -jar BuildTools.jar --rev 1.21.9" installs 1.21.10

is this intentional or a bug and where should this be reported if so

eternal oxide
#

intentional

pale lava
#

if a plugin uses one of these versions how do i obtain said versions then if i cant from build tools

eternal oxide
#

you use teh released version

#

deprecated versions are usually removed due to a bug/exploit

pale lava
#

gotcha so the plugin should update those versions then, they support previous versions and have those as dependencies, i guess they should move the version up until it gets to one that isn't deprecated

eternal oxide
#

correct although minor versions are usually code compatible with prior

#

so a .5 will run fine on a .6 server

pale lava
#

okay awesome

elder lichen
#
public class Testowydc extends JavaPlugin implements Listener {

    private final int ROWS = 20;
    private final int COLS = 4;

    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(this, this);
    }

    @org.bukkit.event.EventHandler
    public void onJoin(PlayerJoinEvent event) {
        Bukkit.getScheduler().runTaskLater(this, () -> setupTab(event.getPlayer()), 20L);
    }

    private void setupTab(Player player) {
        ServerPlayer sp = ((CraftPlayer) player).getHandle();
        List<Entry> entries = new ArrayList<>();
        int index = 0;

        for (int col = 0; col < COLS; col++) {
            for (int row = 0; row < ROWS; row++) {
                String name = "§" + Integer.toHexString((col + row) % 16) + "Slot_" + index;
                GameProfile profile = new GameProfile(UUID.randomUUID(), name.length() > 16 ? name.substring(0, 16) : name);

                Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(
                        profile.getId(),                    
                        profile,                            
                        true,                                
                        0,                                   
                        sp.gameMode.getGameModeForPlayer(), 
                        Component.literal(name),            
                        false,                              
                        0,                                 
                        null                                
                );

                entries.add(entry);
                index++;
            }
        }

        ClientboundPlayerInfoUpdatePacket packet =
                new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER,
                        (ServerPlayer) entries);

        sp.connection.send(packet);
    }
}```  Can someone help me? Spigot 1.21.8

I want this to work.
elder lichen
chrome beacon
#

well yeah that's not going to work

#

You can't just randomly cast stuff

elder lichen
#

Do you want to help me figure out how to do it? The easiest way?

chrome beacon
#

I'm not going to write it for you that's what you're expecting

elder lichen
#

Can you at least give me a hint on how to do it, because apparently it's much harder to do it on Spigot on this version than on 1.20.1?

chrome beacon
#

as I mentioned you can't just cast a list of entry to server player

#

also I'm not sure what "this" version is

elder lichen
chrome beacon
#

You said it's much harder to do on "this" version

#

without specifying what "this" version is

elder lichen
#

version of Minecraft that on 1.20.1 I made a table without problems with fakeplayer and it works, but on 1.21.8 it is much more difficult

chrome beacon
#

I don't recall there being much of a difference

#

Anyways start by fixing that cast

tranquil pecan
#

List<Entry> entries = new ArrayList<>();
inflatable

wide crescent
#

What's the normal value for permissionDefault? I want logblock to be accesible for everyone

tool:
leftClickBehavior: NONE
item: WOODEN_PICKAXE
defaultEnabled: true
mode: LOOKUP
dropToDisable: false
removeOnDisable: true
aliases:
- t
params: area 0 all sum none limit 15 desc since 60d silent
canDrop: true
rightClickBehavior: TOOL
permissionDefault: OP

chrome beacon
#

though in general you'd manage your permissions with a permissions plugin like LuckPerms

#

Assuming that uses the permission default enum set it to TRUE

wide crescent
elder lichen
#
this.playerConnection = ((CraftPlayer) player).getHandle().c;```

spigot 1.21.8 what will it be like now?
thorn isle
#

tip: first check the version you're migrating from, find the member's intermediary mapping, and then just ctrl-f for it in the version you're migrating to

hard socket
#

how can I hide this bundle info?

sacred mountain
#

anyone know how mannequin hitboxes work

chrome beacon
sacred mountain
#

1 sec another couple images sending

#

like what the hell

#

moyang why

#

any way to even know when the player clicks on another part of the entity that isnt in it's hitbox

#

or is this just a limitation

winged scaffold
#

join vc 1 for free development on your server

chrome beacon
sacred mountain
#

for context this is a sleeping pose mannequin entity

drowsy helm
#

but you'd have to calc it yourself

sacred mountain
#

i would need nms for that i assume

drowsy helm
#

uh it might be in api

thorn isle
#

i'd spawn an Interaction entity for that

#

or manually raytrace clicks near the mannequin

#

crawling/sleeping/swimming pose hitboxes aren't really representable with aabb's since they can rotate, which aabb's can't

#

so some manual raytracing is in order if you want to do it accurately

#

for specifically lying in a bed, where the rotation is guaranteed to be axis aligned, you can still use interaction entities

sacred mountain
#

honestly i don't like the way minecraft does hitboxes in general

#

so much more annoying than other games i've modded

#

or made plugins for

thorn isle
#

aabb's make sense for a block game and are cheap and easy to deal with

#

just they don't work for things that can rotate and aren't approximately the same size in x/z

sacred mountain
#

guess so,

#

are villager hitboxes the same when they sleep

thorn isle
#

probably

sacred mountain
#

they dont even have one when theyre asleep i think its a block event to wake them up

thorn isle
#

you can click them, i remember opening the trade gui while they're sleeping, but it's very finicky

sacred mountain
#

i'll probably use an interaction entity in that case, i didnt even know they were a thing lol

young knoll
#

You’ll need 2 interaction entities if you want accurate detection

#

Since they cannot have a different width and length

sacred mountain
#

good enough lmfao

#

i might create an algorithm to make custom sizes out of several of these entities

#

i mean they have tags so shouldnt be too bad

winged scaffold
#

dm me for a fullstack dev if you need help with ur server

drowsy helm
ocean gorge
#
public void handleProxyMessage(byte[] message){
        try(DataInputStream in = new DataInputStream(new ByteArrayInputStream(message))){
            System.out.println("1");
            String subChannel = in.readUTF();
            System.out.println("Valore letto in subChannel: " + subChannel);

            if(subChannel.equals(EndlessTickets.TICKET_SUBCHANNEL)){
                System.out.println("2");
                short len = in.readShort();
                byte[] msgbytes = new byte[len];
                in.readFully(msgbytes);

                DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes));

                String action = msgin.readUTF();

                if(action.equalsIgnoreCase("NEW")){
                    System.out.println("3");
                    int ticketId = msgin.readInt();

                    Ticket ticket = plugin.getTicketManager().get(ticketId);
                    if(ticket != null) plugin.getTicketManager().getStaffNotifier().notifyCreated(ticket);
                    else Bukkit.getConsoleSender().sendMessage("TICKET IS NULL: " + ticketId);
                }else if(action.equalsIgnoreCase("CLAIMED")){
                    // ... Logica per notifica ticket preso in carico ...
                }
            }
        }catch(IOException e){
            plugin.getLogger().severe("Error reading network message: " + e.getMessage());
        }
    }

why do i get that subchannel is "premiumvanish:main" and not the one i want?

buoyant viper
#

how are u sending the plugin message?

ocean gorge
#
public void notifyNewTicket(Ticket newTicket, Player senderPlayer){
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        DataOutputStream out = new DataOutputStream(stream);

        try{
            out.writeUTF("Forward");
            out.writeUTF("ALL");
            out.writeUTF(EndlessTickets.TICKET_SUBCHANNEL);

            ByteArrayOutputStream msgstream = new ByteArrayOutputStream();
            DataOutputStream msgout = new DataOutputStream(msgstream);

            msgout.writeUTF("NEW");
            msgout.writeInt(newTicket.getId());

            out.writeShort(msgstream.toByteArray().length);
            out.write(msgstream.toByteArray());

            senderPlayer.sendPluginMessage(plugin, EndlessTickets.VELOCITY_CHANNEL, stream.toByteArray());

            plugin.getLogger().info("Network notification sent for ticket #" + newTicket.getId());
        }catch(IOException e){
            plugin.getLogger().severe("Network message encoding/sending error: " + e.getMessage());
        }
    }
#

this works, because the log appears

buoyant viper
#

honestly, no clue

#

from what im [attempting to] read [on my phone], ur subchannel should be Forward?

#

oh thats a bungeecord messaging channel command, huh

ocean gorge
#

yeah, it's an in-game support ticket system, however i only get that subChannel is "premiumvanish:main"

#

it doesn't make sense like that

buoyant viper
#

is VELOCITY_CHANNEL set to "BungeeCord"?