#help-development
1 messages · Page 1321 of 1
but my question is, why would you want Bukkit for 1.3.2
I have very big community for these versions
And I need to make my own fork to fix a lot of bugs and expolits
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)
I m using my own plugins (excluding CoreProtect)
Never heard about LegacyFabric, will check it later
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
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
I got it. Then it's better to use bukkit, my players using forge and vanilla clients
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
oh
that's pretty much what plugins are in the end, server mods
Will spigot 1.21.11 be completely embracing mojang mappings or will it be keeping custom spigot names?
I hope for the former.
I don't see a reason to stay with spigot names
?paste
Looking to paste something? Try a code block or one of the following websites:
- https://pastes.dev/
- https://sourceb.in/
- https://mclo.gs/ (best for server logs)
https://mclo.gs/hQE5Y2m
This goes on for about.... an hour or two.. Any big thoughts about this?
Asynchronous chunk updates!
you have a bad plugin. Or one which is not compatible with Spigot
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
huh
a mod that is known for causing that specific error is Better Compatibility Checker
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.
you sure you don't have a modded client?
Like that player is a modded client joining?
There is only two likely things causing that error. Either they have a modded client or their player data is corrupted
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
a modded client indeed can do that and I just told you a mod that causes that error
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
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
How does a modded client trigger a server to modify the world async
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
lol
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
the code of conduct is doing that?
guess, I should make note of that as something else to cause that error that is quite vague
That’ll do it lol, ty for looking into it
well now you also know some other things that would cause it too lol
Ya haha
well, now I have that added to my notes
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
honestly i think im ditching vscode in favour of nvim
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
Honestly I sometimes use mouse instead of memorizing a key in nvim
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
Cool but ssh
Looking for a dev that knows how to sk and config
?services
If you wish to request or offer development/art/building/administration services, please do so at https://www.spigotmc.org/forums/services-recruitment-v2.54/
?paste
Looking to paste something? Try a code block or one of the following websites:
- https://pastes.dev/
- https://sourceb.in/
- https://mclo.gs/ (best for server logs)
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
im trying to detect a right click but no matter what i do it doesn't work anyone got any idea?
Paste Dev Link
assert does nothing at runtime
^ not the correct place to advertise. Post it on teh spigot site
exactly and that's what's powerful about it
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
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.
I agree, asserts are an underutilized feature
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
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
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
that's valid as well
it allows me differenciate internal misbehavings from external ones
there's never a clear-cut best way of doing these things; when in rome
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
one funny thing i use assert for it static flow control analysis
there's @Contract in jetbrains but who tf uses that and its very hard to really write them properly
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
that's a cool exploit for an IDE hinting lmao
i'll take that in mind
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
that's actually so smart
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?
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
But is this random location between the minimum and maximum x and the same for z?
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
wdym
i mean i don't pick a position from an uniform random distribution
some locations are more likely than others
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)
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
yea it is vanilla
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
I didn't understand why async
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
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
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
kill?
Just make the world smaller and reset it often
the thread sleeps for enough seconds to kill the thread
threads don't die by sleeping
either way, i would use an ExecutorService rather than a while loop in a dedicated thread
So if I have a while look loop that takes 5 minutes to iterate, the thread doesn't die
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
I think that's overcomplicating things
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
I think it's simpler to just validate each tick in the main thread and try for a valid location per tick
none of these should happen in normal operation
@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
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
I think this is bad because a person can go to RTP 10 times and not have done anything in all 10 of those times
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
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
that looks like a purely random distribution, i.e. an uniform distribution yes
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
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
So you don't see a problem with RTP with the range I mentioned?
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
yea this is smart
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
In my case, I won't have a biome whitelist, so I don't need that. I don't think a biome whitelist is necessary
well
do you want your players to teleport into an ocean?
no trees to chop there; bad start
In that case, I would check the highest block to see if it block is water at a random location
that requires a chunk load, which must be sync, and is slow
A biome can contain water and not be of the ocean type
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
same applies to a lesser extent to deserts
it's what minecraft generates its terrain from
Yea and for that reason it’s also a shame that it’s only enabled through a flag suggesting you have a different set of errors in prod vs ur test/dev env (which is kinda why it sucks)
there should be a method on the World class for it
myeah, assertions do have their drawbacks
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
I have no idea how to do this
i think World::getBiome does it, i'm not 100%
seems you missed one. Threads die when they complete which is the normal way they should die. Hence a while loop keeping a thread alive as the the while loop condition is never met but when it is, it will die 🙂
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
yes, it seems like i overlooked the obvious 🤡
/**
* 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.
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
@quaint basin what version ru using?
1.21.8
Ah ok
That's the same method lol
But you thought exactly what I thought
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
gpt explained it to me and maybe he's right xd
He seemed convincing to me
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
https://imgur.com/a/7R2B66B idk if this is right
e.g. it won't work on most earth maps where the biome is part of the map data
But it seems so xd
i think it's confusing between the two different meanings of noise here
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
The computed version uses client-side noise. I thought this would be a problem if the client could manipulate the data to say that the biome at certain coordinates was BIOME X, while on the server it was Y, but that's impossible
either way, this should be 100% noise based and not need a chunk
i dont have this method
should exist on 1.21.8 as well
it's just on the WorldInfo interface which World extends
Does not exist on Spigot
oh u said get
judging by the docs/sources he's looking at, he's on paper
yea im on paper
oh i maybe made a typo
now it is provider#getBiome?
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
it is @nonnull
@NotNull BiomeProvider vanillaBiomeProvider();
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
because of callers like us who're using it asynchronously
i.e. we require it to be thread safe
Yes, but for me, saying "must" means that it might not be thread-safe, but in principle it is thread safe
the notes are for the devs implementing the interface
telling them that they must make it thread safe
oh ok
because devs like us expect it to be thread safe
make sense now
You say to use the regular getProvider. If it's null, then should I use the vanillaProvider?
is teh getProvider marked as not null?
prfetty sure its never null
nope you are correct, it can be null
How can I obtain WorldInfo through World?
wouldn't be accurate, but generally it shouldn't lol
Guys, can someone help me with getting minecraft_server pom's? How can I get one by myself?
huh
Without maven
POM
without Maven
?
I mean, without bukkit/spigot maven
u just want to download the vanilla minecraft server?
something like this
vanilla server has obfuscated classes, isn't it?
until now yeah
u need to run some sort of tool to deobf otherwise, which would more or less mean running spigots BuildTools software
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
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
for the record pom is the build metadata file that maven uses to configure a project build, and isn't related to this
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
anyone knowledgeable on how hypixel server instances communicate to eachother
Probably some messaging system
Like Redis
Or maybe they just do it via raw sockets ¯_(ツ)_/¯
redis does have messaging but it's a bit lacking
for dedicated messaging, i'd go with rabbitmq or something
I have like 6gb of mc jars
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!
?services
If you wish to request or offer development/art/building/administration services, please do so at https://www.spigotmc.org/forums/services-recruitment-v2.54/
chances of getting a dev for no money is slim
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
i was giving that guy money for the money services like donos
nahh he busy lmao he cant do it anymore hes workiung
working
but alright my excuses for doing this dumb things and asking for this
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);
}
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?
spigot-api is just the api
If you want the server internals too just use spigot (and run buildtools for that version)
?bt
so am I correct in saying that to use server internals in code, I must provide a spigot jar
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.
Buildtools will install it into your maven local
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
they would run buildtools themselves
supplying the jar sounds annoying given they'd have to put it at the right place
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>
The home of Spigot a high performance, no lag customized Bukkit Minecraft server API, and BungeeCord, the cloud server proxy.
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
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
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.
if it runs before or after depends entierly on where you call map.put
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
I use map.put after the dropItemNaturally call
There was a missing semicolon (;) before Map.put
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
Yes, thank you
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?
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
It doesn't but there's a bit of a trick to get it do so anyway
If you make the player ride on the entity it's currently spectating it should start sending movement packets
you can get keypresses with the input event/packet, but i'm not sure about mouse input
yeah i can do that
mmm i remember this trick
thats true
but camera rotation ?
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
sre
how can i get a chunk spanshot
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
What if a player places a block?
between the time I receive the snapshot and the tp
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
The overhead of taking a chunk snapshot probably isn’t worth saving the overhead of getting the highest block at a location
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
what checks
that the position is valid
like what
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
The tallest block in the world will never be under a cave
cave != ravine
Yeah, I need that too
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
Is your code public?
Shoutout to the MOTION_BLOCKING_NO_LEAVES heightmap
no
what is it
Sadly you could get unlucky and end up picking the column with the tree trunk in it
records the highest position with a block in a block column, ignoring leaves
A block that has collision
no idea how can i use MOTION_BLOCKING_NO_LEAVES
chunk snapshot has getHighesBlock(Heightmap) or something
so does chunk
world maybe too
and can i do that async
the problem with this is a player placing a block meanwhile
I think you technically can read the world async
you can, and it's actually quite safe and performant on paper
wdym buffer
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
why chunksnapshot then
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
it does not have
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
I still don't understand, but okay
I thought you already knew these methods
i alr read evertyhing about chunksnapshot
i do, and i know it's there
and doesnt have anythin about heightmap
but i'm not 100% about the name
Yeah wtf vcs2 you don’t know every spigot method signature off the top of your head?
You don't know about player.sendMessage?
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
What if all positions are unsafe in the buffer?
the data for all the heightmaps is recorded on it, but there's only api for querying the "highest taken" one
shouldn't happen; have a big enough buffer
in the off chance that they are, you can tell the player to try again later
For me, the buffer would be a maximum of 16*16 locations
you'd need like 300 players to use the command within a few seconds to run it dry
I'm not understanding anything 😭
put a reasonable cooldown on using the command and it shouldn't be a problem
Does the buffer represent safe locations for only one chunk?
serverwide
or no, worldwide; or whatever other domain you want, but worldwide makes the most sense
every position in the buffer should be interchangeable
But my range is 50000x50000
so if you want to rtp in the nether, you pop a position from the nether world's buffer
I'm not going to have a buffer of enormous size
it can be 30 million by 30 million, it doesn't matter
A list of 30 million size?
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
And the list of safe positions will be at most 16x16 in size, which is the area of a chunk at a randomly chosen location?
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
Make it dynamic :p
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
If it ever gets down to 0 increase the capacity by 10 or something
When is the buffer created?
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
And when should I reallocate the buffer?
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?
Either I'm stupid or you're explaining things badly because I don't understand anything
You hold a list of valid teleport locations
If its size is < howManyYouWantToHaveBuffered then you calculate a new one
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
when
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
wtf
yes
the fridge has food in it
no
I'm going to have dinner soon
now the fridge has less food in it, yes?
yes
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
Are you suggesting creating a list of safe locations in onEnable?
the grocery store is the position finding algorithm
yes, that's what "at startup" means
You create it at startup
and as the list over time shrinks, you add more positions in it so you don't run out
You fill it over time, as needed
Having this list doesn't make sense because 10 seconds later all those locations on that list could be unsafe locations
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
This is unlikely, but I want to avoid it, but I think you're complicating things
this is what i do, i have a BlockingArrayQueue and a thread blocking on add on it; it'll run whenever there's space
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
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
Why would I be slow-moving, wtf?
Do you want to see the latest plugin I made?
okay now you are just clowning on him
Slow falling
So they don’t take fall damage and can steer themselves away from lava or ravines or whatever
brother i have been trying to explain to you what a buffer is for the past half an hour
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
This is the simple way
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
Wouldn't it be easier to generate a random location when the player types /rtp and check if the chunk contains a safe location, and if it doesn't (16*16 attempts) tell the player to try again?
Sure
I didn't understand why a buffer would be advantageous here
If there are no safe locations in the buffer, you will not be teleported instantly
There should always be safe locations in the buffer
If there aren’t, you need a bigger buffer
There might be a moment when the buffer is empty and the person types /rtp - so they are not teleported instantly
Like I said, the buffer should never get empty
If it does that means you should make it bigger
So I'm going to be checking the buffer every tick?
You could, or you can do as vcs2 said
probably the funniest meme i've ever done
fun fact: that guy (Juan Joya Borja, "El Risitas") was 45 years old at that time
DISCORD: https://discord.gg/mSVkpKv
PATREON: https://www.patreon.com/spartayoshi
TWITTER: https://www.twitter.com/spartayoshiyt
you can have an external program doing this just fyi
to blow your mind that not everything has to run in the server
unless your world is pregenerated and you only teleport to generated areas, that wouldn't be possible
IPC go brrr
yeah, be quite dumb if you don't have a pre-generated world. Lag galore otherwise
I mean, you can only pre-generate so much and random teleport makes it easy to go out of that bound in order to avoid teleporting players too close to eachother
you can pre-generate the entire map?
is this for a minigame? If that's the case then yeah
compute lol
compute?
pregenerating a world can take weeks if the range is big enough
it definitely does not, and besides file size is a concern too
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
takes about 17gb if no nether and end, and probably more like 12 hours
not sure what you are using that it takes so long for you o.O
you can check size with chunky's calculator, it scales pretty badly: https://onlinemo.de/world
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
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
50k blocks is not 500gb
yeah obviously wrong
it isn't though
but it is because most of your world is air blocks
sorry, there is not 500gb worth of data in 50k by 50k
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
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
your perception of how big worlds usually are is just wrong
its not. ran servers before. In terms of amount of storage space minecraft worlds are small
most servers won't pregenerate past 10-20k radius, since that's plenty for a survival for a few years
I have always done 10mil by 10mil
I said this
there is no way that if 10mil by 10 mil is 10gb, that 50k by 50k would be significantly larger
actually 16gb if it is 10x10, you were probably doing 5x5 actually
no
again, if you don't believe it then go pregenerate a world, see how much it takes and what size you end up with
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
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)
10x10? as in 10k or 10mil?
10k radius
wait, you were talking about millions? Lol
because radius in the millons take weeks
you obviously haven't ever generated a world before lol
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
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.
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
Well, it increases by 10% cubed, which is about 33.1%
ignoring time complexity, how did u get 10^7 x 10^7 to fit in like 10^10 bytes?
ig u get 10^2 also if ud consider height
so 10^16 blocks in 10^10 bytes
compression babyyy
and all that in 4h
most of the world in minecraft is air
air blocks don't take up space like you think it does
That sounds wrong
MC does have some optimizations for single block sub-chunks, is that what you mean ?
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
was it full or subchunks that have this
I don't remember exactly
air blocks don't take up space
generate a world and then come back
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
then stop spreading misinformation
you guys act like I am new to MC or something
you sound like it with how you understand world gen lol
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
air compresses rather well but it doesn't take up "zero space"
And chunks also don't consist purely of air lol
air blocks take up no space, you can go look to see how blocks are stored
They have a rather big amount of non-air blocks too
You go look up how blocks are stored
Please
yeah i know how they're stored because I've written tools for this lol
I have? I am quite familiar with the anvil storage spec
You pretty clearly aren't
alright, show me where air is taking up space?
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
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
what are the 0's? never used chunky
x y for center to generate around
ah
technically 20k x 20k then but that should be about 16-17gb according to onlinemo.de
ye 10k radius
sounds about right from your 20%
hmmm....seems I am going to have to manually update WorldBorder
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
Ended the little experiment to stop torturing my PC
31% and I have 4.5GB world
Yes, and the result = enormous processing load just so the player doesn't have to wait 10 miliseconds to teleport.
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 😎
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
I mean
You’d still need the server to generate the chunks
Assuming everything isn’t pregenerated
right, if its not pregenerated
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
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?
does Bukkit#getPlayer(name) just ignore case or something else ?
pretty sure it ignores case
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
so it's case insensitive, but it may not return the player wanted if you're not precise enough
Correct
My summary here is accurate
nerd
10 years of being around Bukkit does that to a guy
hey
this is the new locator bar, is it possible to create these points? in the code?
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
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
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?
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
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
"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
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
Maybe you could PR it
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);
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.
You’d have to use some sort of system to intercept logging
But this seems like
?xy
yes it is lol
Im trying to get nbt of an entity
but I want to avoid using the NBT API
What NBT do you want
Theres a way to intercept logging with bukkit? Like through an event?
Pretty much all of it should be available through api methods
getHealth for health, getEquipment for armor and held items, etc
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
What do you want to do with it
duplicate an entity. copy its exact current state at a specific tick and duplicate it at a later point.
Version?
latest
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
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
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
Yeah, I tried the NMS path, and it would be pretty straightforward if I knew how to create an instance of net.minecraft.world.level.chunk.LevelChunkSection. If I were able to do that, I would just feed the buffer into its read method and call it a day
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
public LevelChunkSection(Registry<Biome> biomeRegistry, Level level, ChunkPos chunkPos, int chunkSectionY)
i assume you're having trouble finding the biome registry?
Yes, as well as Level
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
Uh...
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
I wondered about it, by the way. Wouldn't it be very slow for this kind of packet? I know it might be an obviously naive question, but I genuinely have no idea about the internal kitchen here. It's my first time messing around with the protocol
By the way, I tried to listen for ClientboundRegistryDataPacket to get the registry, and indeed it sends something with the resource key ResourceKey[minecraft:root / minecraft:worldgen/biome], but I was kind of stuck there, because I didn't know how to convert it to Registry<Biome>, so I dropped this idea
you only need to get it once per world per session
Huh... Good point
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
Yes, I guessed that. It also sends a bunch of entries along the key, but I was kind of lost about what to do with them. I had the hypothesis that since they are sent over the web, and the client needs to decode them somehow, there must be a method to convert those back to Registry<Biome> somewhere, but I gave up looking for it, it's too difficult
So yes, I'll probably try this hack. Thanks
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
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
i assume you're trying to implement this yourself?
just trying to determine whether i should clown emote him or not
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)
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
okay
then what should i use Executor Service?
for asynchronous tasks, yes; for main thread tasks, no, you're stuck with the bukkit scheduler
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
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
Hmm.. I wasn't aware of it :D .. can you give me a class name?
Structure
declaration: package: org.bukkit.generator.structure, class: Structure
Just make sure it’s the right structure class… there’s like 3
this requires me to do a whole lot of things
declaration: package: org.bukkit.structure, interface: Structure
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
But it doesn't take a file anywhere
StructureManager
ohh I see, so Structure can be a schematic?
how do you create one? if I build a house and want to save it as NBT
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
with the structure file, are entities and all of the rotation data saved too?
eg. paintings, armor stands
Yes
perfect
so I have to first load litematic files and then save them as nbt, too much work 😿
Might exist a converter somewhere
ill save you as a structure emily
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.
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 :)
I think I got it.
It's logically possible but not stable so api don't give access directly.
Thank you for detailed reply.
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
Looks like a problem with m2e:
https://github.com/apache/maven-jar-plugin/issues/506
https://github.com/eclipse-m2e/m2e-core/issues/2084
ahaha, I did it!!!
Thank you, if I ever publish this plugin I'll credit you
💪
What are you using maven jar for?
To compile?
Probably to set manifest entries
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
?services
If you wish to request or offer development/art/building/administration services, please do so at https://www.spigotmc.org/forums/services-recruitment-v2.54/
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
You could make it grow with the scale attribute
obligatory: probably core shaders for the visual effect
i would add a giant text display next to the bee that reads "this bee is about to explode"
make it shoot small honey blocks into all directions when it explodes which stick to the surroundings
Countdown in display name
Objects.requireNonNull(getCommand("spawn")).setExecutor(new SpawnCommand(worldTeleportManager));
Is this required
or can I just do it without .requireNonNull
You can do without. All it does is quiet an IDE warnign about a possible null
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
// 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
🤡 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"
lol
i would rather like to meet an idiot who decided this was a good idea and was needed, i mean just look at it "!", it helps so much. oh my god!!
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
Run it in-game and hover over it
are you implying that it does have practical value ?!?!
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
Yes
Hello, I need someone who knows how to make fakeplayer tablists, 4 columns, 20 rows each, version 1.21.8
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
not the place for that
but you can send the error and your code and perhaps someone will offer guidance for free
Show your code
I'll write tomorrow, okay? I'm going to bed because I have to get up early for work tomorrow.
also remember to include the error if you are getting one
anyone need a minecraft dev reach out to me
?services
If you wish to request or offer development/art/building/administration services, please do so at https://www.spigotmc.org/forums/services-recruitment-v2.54/
if free yes
only free. especially when you use ai
AI isn't always bad
It's good for finding obvious errors in code
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");
}
}
}
are you registering the listener?
code looks fine
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!");
}
}
That's not how you register listeners
The home of Spigot a high performance, no lag customized Bukkit Minecraft server API, and BungeeCord, the cloud server proxy.
look at 1.4
getServer().getPluginManager().registerEvents(new MyListener(), this);
alright thanks i'll try
Bukkit needs to know the listener exists, if not it will just sit there
so this getServer().getPluginManager().registerEvents(new HoeEvents(this), this);?
thanks you kind sir
it work
🙂
Any way to change the opacity of particles, plugin or texturepack?
shader/resourcepack
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
Get the config value then you can use Material#matchMaterial
Material.matchMaterial
aight thank y'all ill try that rn
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
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
what's a block display default brightness
whats its full brightness
15 sky 15 block
Ok thanks but how to set the brightness then
Have you tried setBrightness?
sob
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
intentional
if a plugin uses one of these versions how do i obtain said versions then if i cant from build tools
you use teh released version
deprecated versions are usually removed due to a bug/exploit
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
correct although minor versions are usually code compatible with prior
so a .5 will run fine on a .6 server
okay awesome
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.
^
Do you want to help me figure out how to do it? The easiest way?
I'm not going to write it for you that's what you're expecting
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?
as I mentioned you can't just cast a list of entry to server player
also I'm not sure what "this" version is
I don't understand
You said it's much harder to do on "this" version
without specifying what "this" version is
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
List<Entry> entries = new ArrayList<>();

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
That sounds like a question for #help-server
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
I took OP from myself and it works so I assume it should be done, thanks
this.playerConnection = ((CraftPlayer) player).getHandle().c;```
spigot 1.21.8 what will it be like now?
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
how can I hide this bundle info?
anyone know how mannequin hitboxes work
tried hide additional tool tip itemflag?
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
join vc 1 for free development on your server
Don't post in every channel nor advertise your services here
anyone know?
for context this is a sleeping pose mannequin entity
you could maybe modify it's aabb hitbox
but you'd have to calc it yourself
i would need nms for that i assume
uh it might be in api
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
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
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
probably
lmao
they dont even have one when theyre asleep i think its a block event to wake them up
you can click them, i remember opening the trade gui while they're sleeping, but it's very finicky
i'll probably use an interaction entity in that case, i didnt even know they were a thing lol
You’ll need 2 interaction entities if you want accurate detection
Since they cannot have a different width and length
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
dm me for a fullstack dev if you need help with ur server
bro how many times do you want to post lol
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?
how are u sending the plugin message?
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
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
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
