#help-development
1 messages · Page 1277 of 1
that's the one yeah
I can set damage in projectile hit event?
or are you saying I should use Damage event instead?
you modify damage in the damage event
finally got it working https://github.com/DepressyPresti/ATPStickMenu
hey bois and gals and all others.
I need to detect how much damage is taken in the entity damage event to the player
but using shields wont work.
cuz all damage triggers my check even if the players has their shield up
So if the shield is up you don’t want the listener to trigger?
basically
if the players loses two or more hearts in one damage instance
they explode
kaboom
but this also triggers even if the player blocked wiotha shield
I need to get the actual final damage after blocking as well
would it maybe make more sense to check the player health every tick? this way two attacks from different sources during the same tick would also make a player explode if they deal 2+ hearts of damage in total
that'd be too much rewriting
I need it done like.. now
im mid recording :(
passiveEffect();
}```
this is what i have now
i mean you just get rid of the listener and replace it with a task and plug your logic into it with the "damage" being previous health - current health
there could be a better way with the listener too but i don't know one off the top of my head
there is, but i don't know if it applies the shield
It does
lemme try
that should work then
It would also account for like armor and potions so you wouldn’t have to worry about those either
what's an easy way to get the blocks of a piston extend or piston retract event after the piston has fully extended/retracted? the blocks on a stick piston and slime block don't trigger any block physics events, and when i try to get the block at the time of move when the piston activates, they're just a moving_piston block data
you could always schedule a task in the piston extend/retract event (which iirc has a getter for the affected blocks) to check them later
off the top of my head i think the moving_piston state persists for 4 ticks but i could be wrong; experiment with the timing
yeah i guess ill have to hardcode an exception for that
im not a huge fan of being forced to add checks for a specific block type though
what exactly are you doing? there could be a better way around it
im trying to get all block data changes
so if a piston pushed a block from location a to b, i'd want to get the conversion from air -> block or block -> air
instead im getting air -> moving_piston
and not getting the final block type, since that doesn't trigger a block physics event
does this only happen for the piston arm block or all the blocks that are pushed by the piston
i don't really remember how pistons work internally
all blocks pushed by the piston
iirc the event is cancellable, so at the time of the event, the actual extension/retraction shouldn't have happened yet; are you sure you see the moving_piston during the event, or are you checking afterward?
well actually i have a listener for BlockPhysicsEvent, and i add the location of the block to a collection, then in a repeating task every tick, i get the block data at that location and compare it with what i had before
listening to the piston retract/extend doesn't help because like u said the piston push takes 4 ticks
i think im just going to have to check if the block data is a moving piston, and if so, then re-add the location back to the queue
you can grab the block types in the retract/extend event and store them for later use in the physics event or whatnot
well then id need to calculate where the blocks are being moved to
they move 1 block away from the piston if extending, 1 block toward the piston if retracting
well yes, but the direction and everything is something id need to calculate
either way you're interested in what block changes to what block, i.e. block type changes; so grab the previous block type in the event, then schedule a task to n ticks away, and compare
and you have a direct before-after mapping
yeah
for any given location you can see what it is now; and from the stored types, what it was
It tells you the direction
i got it working with fetching the block type on a later tick if it's a moving_piston, but i think i'll have to listen to the piston events eventually anyways. thanks
im using location.getBlock.setType, this works for items but not spawning blocks
BlockState -> Skull -> has the same set profile method as ItemMeta
block.setType(getHeadMaterial());
try {
String json = "{\"textures\":{\"SKIN\":{\"url\":\"" + textureUrl + "\"}}}";
String base64 = Base64.getEncoder().encodeToString(json.getBytes());
Object profile = Class.forName("com.mojang.authlib.GameProfile")
.getConstructor(UUID.class, String.class)
.newInstance(UUID.randomUUID(), "customHead");
Object propertyMap = profile.getClass().getMethod("getProperties").invoke(profile);
Class<?> propertyClass = Class.forName("com.mojang.authlib.properties.Property");
Object textureProperty = propertyClass
.getConstructor(String.class, String.class)
.newInstance("textures", base64);
propertyMap.getClass().getMethod("put", Object.class, Object.class)
.invoke(propertyMap, "textures", textureProperty);
if (block.getState() instanceof Skull) {
Skull skull = (Skull) block.getState();
Field profileField = skull.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
profileField.set(skull, profile);
skull.update(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}``` this just spawns a normal untextured skull and throws errors, this logic works for items tho
That’s not what the guide says to do
oh
ok ill have a look thanks
does the guide work for textures that arent registered to a skin?
Yes
No it does not
All textures are registered to a skin
That is how skulls work
The texture data is just an encoded url to the skin
@EventHandler
public void onExit(VehicleExitEvent e) {
if (gameManager.gs != GameSelected.ICEBOATRACING || gameManager.gameState != GameState.ACTIVE) {
return;
}
if (!gameManager.alive.contains(e.getExited().getUniqueId())) {
return;
}
e.setCancelled(true);
}
hi for some reason theres a bug that happens to some players where when they leave the boat client sided but on the server they're still in a boat
1.21.4
update
Well yeah, but it doesn’t have to be a live skin
That's true
If I'd want to exit a player out of the Sign creation interface after placing a sign I'd cancel the PlayerSignOpenEvent?
yes
Hi, so basically I added legacy back and it didn't work. after tracing my steps, when I added modern it worked fine for all client versions. I traced every commit and got that I removed forge support which breaks it.
I kind of rewrote pluginmessaging which I guess breaks it
what is allowExtendedPacket?
inn plugin messaging
modern works in bungeecord 🔥
it broke bcz i removed server login handler 💀
there's an issue with my Biome Checks in my plugin
if (gameBiome.equals(Biome.OCEAN)
I have a bunch of these checks using 1.21.4 api
but in 1.20.6 api block.Biome is an Enum class
how would I check for a biome type without clashing?
I don't understand why this is an issue
equals works fine on enums as well no?
yes
java.lang.IncompatibleClassChangeError: Found class org.bukkit.block.Biome, but interface was expected```
i see ill try using == then
That’s a different error…
if you are using 1.20 API, set API version in your plugin.yml accordingly
That won’t work still
I'd like to ensure support for 1.20.6 while staying in 1.21.4
if you want 1.20.6 support, then you have to code against 1.20.6
there's no avoiding that, unless you make two different plugins for it
that said, the server will take care of making sure it works fine in 1.21.4, so you don't have to worry about that
the stack trace points to that exact if check
you might have to work around some things when it comes to behavior changes between versions but as far as API changes go, the server has a bunch of logic to make sure things "just work" out of the box when using an older plugin
hopefully you aren't supporting a version that old for it to need to initialize that bs lol
I started to just have a separate artifact for say, 1.8 support back in 1.16
can't even imagine trying to support all the way from 1.8 to 1.21.4 in a single artifact
Things still might gonna break with breaking API changes throughout the versions, it would be so fucking annoying to keep track of them all for a single artifact
eh, breaking API changes are at least noticeable from the get-go
the more annoying ones are the behavior changes, where logic that used to work fine just doesn't and that doesn't necessarily introduce an actual stack trace or anything, just the behavior of your plugin completely going bonkers at times
Oh yeah… that’s going to be ass
Whose idea was it for backwards compatibility in the first place
I think Bukkit was designed with that purpose since the start right?
my personal nightmare was 1.9 and its introduction of the off-hand
I can't count the amount of times I had to fix up an interact event in some plugin due to it being called twice after 1.9 lol
it was one of the goals, yeah
however everyone outside the bukkit space seems to have a distaste for Bukkit since it is way too intrusive
people nowadays like more minimal approach like Fabric at the cost of not having an actually useful API for anything
I'll take Bukkit's intrusiveness anytime over the mess that is upgrading mods to newer versions
Yeah, I honestly prefer developing with an actual API rather than injecting Mixins everywhere lol
Fabric barely has any events
Does any1 have any resources about how to disable tab command completion, or at least hide all possible commands?
how to disable clouds
@EventHandler
public void onJoin(PlayerJoinEvent e) {
e.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, PotionEffect.INFINITE_DURATION, 255, true, false, false));
PlayerManager.onJoin(e.getPlayer());
e.setJoinMessage("§x§0§0§f§f§6§6[✔] " + e.getPlayer().getName());
if (!e.getPlayer().hasPlayedBefore()) {
e.getPlayer().teleport(SpawnCommand.spawn);
}
and why does this not teleport players to spawn?
everything else works
also
java.lang.NullPointerException: Profile name must not be null
at java.base/java.util.Objects.requireNonNull(Objects.java:259) ~[?:?]
at com.mojang.authlib.GameProfile.<init>(GameProfile.java:31) ~[authlib-6.0.57.jar:?]
at org.bukkit.craftbukkit.v1_21_R3.profile.CraftPlayerProfile.buildGameProfile(CraftPlayerProfile.java:186) ~[spigot-1.21.4.jar:4458-Spigot-73860e0-fb3f2b6]
at org.bukkit.craftbukkit.v1_21_R3.block.CraftSkull.setOwnerProfile(CraftSkull.java:115) ~[spigot-1.21.4.jar:4458-Spigot-73860e0-fb3f2b6]
at com.czrbyn.customFruits.factories.TreeConstructorFactory.placeBlockWithTexture(TreeConstructorFactory.java:39) ~[?:?]
at com.czrbyn.customFruits.factories.TreeConstructorFactory.constructAppleTree(TreeConstructorFactory.java:27) ~[?:?]
at com.czrbyn.customFruits.fruits.apple.AppleTreeManager.updateTrees(AppleTreeManager.java:30) ~[?:?]
at com.czrbyn.customFruits.utils.Scheduler$1.run(Scheduler.java:19) ~[?:?]
at org.bukkit.craftbukkit.v1_21_R3.scheduler.CraftTask.run(CraftTask.java:82) ~[spigot-1.21.4.jar:4458-Spigot-73860e0-fb3f2b6]
at org.bukkit.craftbukkit.v1_21_R3.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:415) ~[spigot-1.21.4.jar:4458-Spigot-73860e0-fb3f2b6]
at net.minecraft.server.MinecraftServer.c(MinecraftServer.java:1502) ~[spigot-1.21.4.jar:4458-Spigot-73860e0-fb3f2b6]
at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:1391) ~[spigot-1.21.4.jar:4458-Spigot-73860e0-fb3f2b6]
at net.minecraft.server.MinecraftServer.y(MinecraftServer.java:1093) ~[spigot-1.21.4.jar:4458-Spigot-73860e0-fb3f2b6]
at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:329) ~[spigot-1.21.4.jar:4458-Spigot-73860e0-fb3f2b6]
at java.base/java.lang.Thread.run(Thread.java:1583) [?:?]
``` got this error when following the guide
Show your code
?paste
PlayerProfile profile = getProfile(url);
b.setType(Material.PLAYER_HEAD);
Skull skull = (Skull) b.getState();
skull.setOwnerProfile(profile);
skull.update(false);
}
private static PlayerProfile getProfile(String url) {
PlayerProfile profile = Bukkit.createPlayerProfile(RANDOM_UUID);
PlayerTextures textures = profile.getTextures();
URL urlObject;
try {
urlObject = new URL(url);
} catch (MalformedURLException exception) {
throw new RuntimeException("Invalid URL", exception);
}
textures.setSkin(urlObject);
profile.setTextures(textures);
return profile;
}```
I don’t think it likes the profile having no name
Try createPlayerProfile(uuid, “customhead”)
whats the best way to reset my arenas?
How big are they
Like not that much
suppose i have a spleef arena
i wanna reset it
after each game ends
Can just use FAWE schematics
Or if they are on the larger side, SWM
Yep
i am using 1.21.4
swm doesnt support it
@drowsy helm ?
Yes?
swm isnt compataible for 1.21.4
Use FAWE then
alr
1.20.2, 1.20.4, 1.20.5 to 1.21.2 and 1.21.5 - FastAsyncWorldEdit actively develops against and supports these versions.
❌ Any version not listed is not supported.
bre
someone know how to hide attribute in 1.21.4 ? ```final ItemStack item2 = new ItemStack(Material.DIAMOND_SWORD);
final ItemMeta meta = item2.getItemMeta();
meta.setDisplayName("Test Item with dummy modifier");
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
meta.addAttributeModifier(Attribute.GENERIC_LUCK, new AttributeModifier(
new NamespacedKey(String.valueOf(this), "dummy"),
0,
AttributeModifier.Operation.ADD_NUMBER
));
item2.setItemMeta(meta);
player.getInventory().addItem(item2);```
That looks about right
this code hide attributes but it removes them too I still want attack damage etc 🤔 ```final ItemStack item2 = new ItemStack(Material.DIAMOND_SWORD);
final ItemMeta meta = item2.getItemMeta();
meta.setDisplayName("Test Item with dummy modifier");
meta.addAttributeModifier(Attribute.GENERIC_LUCK, new AttributeModifier(
new NamespacedKey(plugin, "dummy"),
0,
AttributeModifier.Operation.ADD_NUMBER
));
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
item2.setItemMeta(meta);
player.getInventory().addItem(item2);```
ok I will try that thank you
Material has a getDefaultAttributeModifiers
sorry I'm new to java but when you said re add it this suppose to work because i got no error but still not adding them back ? ``` final ItemStack item2 = new ItemStack(Material.DIAMOND_SWORD);
final ItemMeta meta = item2.getItemMeta();
meta.setDisplayName("Test Item with dummy modifier");
// Add your dummy attribute first
meta.addAttributeModifier(Attribute.GENERIC_LUCK, new AttributeModifier(
new NamespacedKey(plugin, "dummy"),
0,
AttributeModifier.Operation.ADD_NUMBER
));
// Add the hide attributes flag
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
// NOW loop through all attributes from the original item and add them back
ItemMeta originalMeta = item.getItemMeta();
if (originalMeta != null && originalMeta.hasAttributeModifiers()) {
for (Attribute attribute : originalMeta.getAttributeModifiers().keySet()) {
for (AttributeModifier modifier : originalMeta.getAttributeModifiers(attribute)) {
meta.addAttributeModifier(attribute, modifier);
}
}
}
// Apply all changes at the very end
item2.setItemMeta(meta);
player.getInventory().addItem(item2);```
You need this
omg it works I spent so many hours on this thank you both of you ! 😄 Multimap<Attribute, AttributeModifier> defaultAttributes = item2.getType().getDefaultAttributeModifiers(); if (defaultAttributes != null && !defaultAttributes.isEmpty()) { for (Attribute attribute : defaultAttributes.keySet()) { for (AttributeModifier modifier : defaultAttributes.get(attribute)) { meta.addAttributeModifier(attribute, modifier); } } }
Im wondering to try to reboot my old dead minecraft server's idea during this summer but im not too sure
i mean i always wanted to make custom prison type server but everytime i tried to do it, uni and other work just halted it
for making a teams plugin i should use for store team leader, team members, teams settings etc?
I mean the formal answer is a database
But you can get away with just using json or yml or whatever
but the best way is a database right?
boom c'est la fin
congrats
i have a 16x16x256 bukkit.Material array, can i replace an entire chunks blocks with this at once?
With nms and some hacks yes
where should i look?
At the chunk
just use the WE/FAWE api tbh
^^
save yourself the hassle of messing with internals and potentially messing things up
WE is so widespread it's not hard to just depend on it and not worry
merci :p
Yeah its a private server anyway so ill just go with that
Any idea why I might be getting an UnsupportedOperationException when trying to generate a Pale Oak Tree with generateTree. It only happens sometimes, other times, the tree succeeds
stacktrace?
[14:43:43 WARN]: at org.bukkit.craftbukkit.util.DummyGeneratorAccess.getLevel(DummyGeneratorAccess.java:58)
[14:43:43 WARN]: at net.minecraft.world.level.levelgen.feature.treedecorators.PaleMossDecorator.lambda$place$6(PaleMossDecorator.java:61)
[14:43:43 WARN]: at java.base/java.util.Optional.ifPresent(Optional.java:178)
[14:43:43 WARN]: at net.minecraft.world.level.levelgen.feature.treedecorators.PaleMossDecorator.place(PaleMossDecorator.java:59)
[14:43:43 WARN]: at net.minecraft.world.level.levelgen.feature.TreeFeature.lambda$place$8(TreeFeature.java:155)
[14:43:43 WARN]: at java.base/java.lang.Iterable.forEach(Iterable.java:75)
[14:43:43 WARN]: at net.minecraft.world.level.levelgen.feature.TreeFeature.place(TreeFeature.java:155)
[14:43:43 WARN]: at net.minecraft.world.level.levelgen.feature.Feature.place(Feature.java:190)
[14:43:43 WARN]: at net.minecraft.world.level.levelgen.feature.ConfiguredFeature.place(ConfiguredFeature.java:25)
[14:43:43 WARN]: at org.bukkit.craftbukkit.CraftRegionAccessor.generateTree(CraftRegionAccessor.java:301)
[14:43:43 WARN]: at org.bukkit.craftbukkit.CraftRegionAccessor.generateTree(CraftRegionAccessor.java:204)```
beat me to it
When exactly is this code being run
I have it setup that when I right click a sapling it grows, for testing
Pale oak generates ~30% of the time, dark oak generates 100%
spigot ver from pom 1.21.4-R0.1-SNAPSHOT
full output of the /version command?
T'es français my guy?
[14:52:10 INFO]: This server is running Paper version 1.21.4-231-ver/1.21.4@09e9afd (2025-05-19T17:59:36Z) (Implementing API version 1.21.4-R0.1-SNAPSHOT)
You are running the latest version
Previous version: 1.21.1-131-84281ce (MC: 1.21.1)
Québécois^^
Nice
switched jar to spigot to see if it matters, same issue without paper
[15:08:25] [Server thread/WARN]: java.lang.UnsupportedOperationException: Not supported yet.
[15:08:25] [Server thread/WARN]: at org.bukkit.craftbukkit.v1_21_R3.util.DummyGeneratorAccess.a(DummyGeneratorAccess.java:58)
[15:08:25] [Server thread/WARN]: at net.minecraft.world.level.levelgen.feature.treedecorators.PaleMossDecorator.a(SourceFile:65)
[15:08:25] [Server thread/WARN]: at java.base/java.util.Optional.ifPresent(Optional.java:178)
[15:08:25] [Server thread/WARN]: at net.minecraft.world.level.levelgen.feature.treedecorators.PaleMossDecorator.a(SourceFile:65)
[15:08:25] [Server thread/WARN]: at net.minecraft.world.level.levelgen.feature.WorldGenTrees.a(SourceFile:159)
[15:08:25] [Server thread/WARN]: at java.base/java.lang.Iterable.forEach(Iterable.java:75)
[15:08:25] [Server thread/WARN]: at net.minecraft.world.level.levelgen.feature.WorldGenTrees.a(SourceFile:159)
[15:08:25] [Server thread/WARN]: at net.minecraft.world.level.levelgen.feature.WorldGenerator.a(SourceFile:168)
[15:08:25] [Server thread/WARN]: at net.minecraft.world.level.levelgen.feature.WorldGenFeatureConfigured.a(SourceFile:28)```
?whereami
I always wanted to use that command
scroll down
it seems to be an issue with the decorator, which I dont even need. The decorator is for natural world generation, trees that are bonemealed dont actually get decorators. Is there any method that generates a tree like what bonemeal does
hey fellas, if you use PDC to save custom entity data across chunk load/unload, would that apply to across server restarts as well?
yes
I have players launching custom snowballs that do damage, but the killer is not being properly credited.
My problem: player launches projectile -> ProjectileHitEvent: event.getEntity().damage(damage, projectile); -> PlayerDeathEvent: event.getEntity().getKiller() is null
It works when I do hitEntity.damage(damage, projectile.getShooter()) instead, but I need it to recognize the damage source as a projectile so that stuff like projectile protection is factored into damage calculation.
What's the easiest way to make the damage natural (with projectile protection applied) while properly crediting the killer so that PlayerDeathEvent#getEntity().getKiller() works?
Is there a way to set damage in EntityDamageEvent that would work?
Sure
Just set the damage
Use EntityDamageByEntityEvent and check if the damager is your custom snowball
use damage(amount, DamageSource) not damage(amount,entity)
got a situation fellas
why might an event not be firing at all even if it is registered?
I added print line debugging at the start even and those dont hit
What event are you listening for
PlayerInteractEvent
Are you right clicking air without holding an item
so any idea why generating a pale oak tree causes an exception ~80% of the time
yeah thats what I've concluded, just not sure if its a spigot bug or not
Ill make a jira for it, any way to generate a tree without generateTree? like whatever gets called when a bonemeal succeeds instead
im at my wits end what on earth
these events used to be just fine
now i cant figure out wuts going on
No
oh my god i fixed it
my custom mobs spawn egg
i had to set EventPriority since two onPlayerInteract events were conflicting since one was cancelling
Wait until you find out you can set all that data in the egg item itself
Wait til you find out that could have just been nbt on the egg
...
We thought the same thing xd
oh actually i do kind of use custom data on the egg to detect if it's supposed to be a custom egg
tell me ur thoughts
maybe this will help someone someday, this is how i deny arrow damage for mobs 10 blocks away from player
public class DenyArrowsListener implements Listener {
@EventHandler
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
Entity damagedEntity = event.getEntity();
if (!(damagedEntity instanceof LivingEntity)) {
return;
}
if (event.getDamager() instanceof Arrow arrow) {
if (!(arrow.getShooter() instanceof Player player)) {
return;
}
// oh... we don't even have to calculate it ;-;
double distance = player.getLocation().distance(damagedEntity.getLocation());
if (distance > 10) {
event.setCancelled(true);
arrow.remove();
}
}
}
}
SpawnEggMeta lets you set the entity it will spawn
Well, EntitySnapshot
wait ur so right
@EventHandler
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
Entity damagedEntity = event.getEntity();
if (!(damagedEntity instanceof LivingEntity)) {
return;
}
if (!(event.getDamager() instanceof Arrow arrow)) {
return;
}
if (!(arrow.getShooter() instanceof Player player)) {
return;
}
// oh... we don't even have to calculate it ;-;
double distance = player.getLocation().distanceSquared(damagedEntity.getLocation());
if (distance > 10) {
event.setCancelled(true);
arrow.remove();
}
}
oh my god that too
Seems MD was quick to fix this one :p
md lurking in the chat
Well they did make a jira ticket
ah
huh, where
Update spigot
oh I see thanks
Can you guys review my plugin maybe
https://www.spigotmc.org/resources/castle-siege-king-teams-kits-abilities-coins-multi-arena-stats-map-more.115123/
sorry if im in wrong channel
You want the code reviewed?
You can click the threads button on the top right
ty
Why are none of your variables private in your main class
just a nonchalant openbook
Custom names for managing entities? Really?
Single letter variable names, event listener classes being named SomethingEvent
wow
check pins <3
Oof
I see
Can someone explain this to me? It's Spigot 1.21.5
What are you building against?
1.21.5-R0.1-SNAPSHOT
and is your server also 1.21.5
yep
show a /version
Update
There might be a chance within those 4 versions
That changed and the method was added or something
Wait never mind
You decompiled the server Jar
Yeah I have no clue lol
the method is in Cow, not AbstractCow
but why are you using reflection to set the cow variant
Oh I just realized that
check this
and this
when I said the method exists, I meant I even tried using reflection to check it, but that didn’t work either. Initially, I wasn’t using reflection, as you can see above
can you send the whole stack trace?
the getKeyOrThrow javadocs don't specify which exception it throws however I would find it weird for it to throw a NoSuchMethodError
ah it throws an IllegalStateException
hmmm
seems they wouldn't need getKey() at the end of getKeyorThrow()
would be redundant otherwise
What is api-version in plugin.yml
they both return a namespacedkey and javadocs says getKey() is deprecated
getKeyOrThrow returns a NamespacedKey, then NamespacedKey#getKey returns the namespace in question as a String
that isn't what I am seeing
they both return a NameSpacedKey
just one does so differently then the other
but getKey() is deprecated and getKeyorThrow() or its other two are recommended
you're looking at Cow.Variant#getKey, not NamespacedKey#getKey
ah, your right
I guess maybe its what md suggested then
or they are really not updating the server jar =/
They’re using latest though
they sent the /version output
well, 4 versions behind but yeah, pretty much
I asked to update and he updated and same issue
assuming they are putting stuff in the right place, IE do they have more then one server or directories of files?
have seen people come in here before where they are updating a server, just not the correct one they are running tests from 😛
anyways, most likely its probably what md said we will just have to wait I suppose
I’m so confused though, does api version in plugin configuration like restrict certain things?
yeah, or it can cause legacy methods to be injected/used
That’s what I thought but
I wouldn’t expect it to like prevent something that exists?
well sometimes something that exists, wasn't the same in a legacy variant
so its possible to have a method exist as a legacy and non legacy form
That’s true
in terms of injection, the last thing loaded on the path is king
if I remember that correctly
chat chain (not chat signing) is just a number which goes up by one everytime a chat is sent?
Hello, I'm looking for the craftBukkit repository, but I can't find it. Could you help me?
?stash
Its on stash
Olivio is an AI from the government
📱 🔥
swedish government yep

Is there a way to get ALL permissions that the server has registered? For example, from every plugin on the server.
You mean registered as in, exposed by plugins, or rather permissions directly used / assigned to groups?
Yeah exposed by plugins
declaration: package: org.bukkit.plugin, interface: PluginManager
#getPermissions()
Does this only show the ones from my plugin, or also from any other plugin?
All
All loaded plugins
a permission would be visible in this Set, such that it is exposed in the plugin.yml file.
Which it is definitely going to be, no one does raw permission comparisons afaik
Alright, thank you! :)
hey chat, what's a good gui lib y'all have used
(for like chest inv, mainly need multiple pages & submenus)
https://github.com/incendo/interfaces but it is sadly unmaintained
in the meantime I found https://github.com/NichtStudioCode/InvUI which seems really nice, thoughts?
triumph gui is also good I've heard
I used stefvanschie's IF and it works fine
I have also seen people recommend DevNatan's inventory-framework
if you want something simpler, then there's also TriumphGUI
other than that, I don't know any other that have passed the test of time
I am always in doubt of whether that's the best approach to GUIs nowadays
given the API was heading towards a more InventoryView-centric approach, but Y2k disappeared so I am unsure of whether the API is heading in that direction anymore
we love resource packs
the concept of Inventories vs InventoryViews is rather blurry on the bukkit side to begin with, given the API pushed for holding the Inventory instances instead of the InventoryViews like the server internals do
hopefully we get 1.21.6 soon so we can get rid of anvil inventory inputs and use actual interactive UI for text input and what not
kyori has already said they will not be adding API for it into adventure, sadly
pog
md coming out swinging WW
that is surprising, did they elaborate on that
your code style scares me
Nevermind MD is 3 parallel universes ahead of me
"we're skill issued frfr"
there was some more stuff hold on lemme try and find it
so they just want to wait things out since Mojang changes things too frequently
I understand that, however I find that to be a rather passive approach
I guess that’s fair
you could just release an API filled with @APIStatus.Experimental all over it
and good riddance
the spigot experience
well, if they aren't going to provide API for it on adventure then I hope they provide some level of raw access to them in Paper so that people at least can build their own APIs off of it
yeah iirc paper was planning to make some API
well, people are probably just going to use packets directly for it like they always did anyway
so I guess it isn't that bad
You can't
Not on adventure at least
Then you lock the API to be Minecraft version specific
Paper is going to have full support for both registry and inlined Dialoges
A thing adventure also cannot nicely abstract given registry types are involved (bungee just doesn't care in the first place, it'll also only do inlined stuff)
What’s the point of registry dialog if you can do inline
Pause menu links and the hotkey e.g. only work on registered ones
Yea
G
Interesting
yet another key people are going to use for some gun special effect plugin
api-version: 1.14
well that's your issue then
Press G to gun
yooo wtf
why that sheep color...
ahem javier, please explain the content by which you have puppeted
I guess it's not necessary to support a version that isn't used... but if I use api-version: 1.21, will it be compatible with 1.16?
it won't
😿
if you want to have 1.16 support, you either make a different module & artifact for it or use 1.16 API
You cant use the Variant feature, and then expect to support lower versions.
which means you will have to use reflection to access the newer API
I have the versions separated by modules
But
Or just make sure you don’t call the new api on old versions
I don't want to have to compile more than once
I don't do it, but I guess I won't be able to use the new methods unless I change the api-version to 1.21
I just tested it, and it requires me to use api-version: 1.21.5; even with other 1.21 versions, the error still shows up.
😿
The only thing limiting me is the api-version in plugin.yml. Is there no way to bypass this limitation for now?
there is not
you just can't support multiple API versions on the same artifact
unless you do so reflectively, and it sucks
Its not too bad so long ans you have a util class to check method availability
thats what I do
So long as you hide the method call under an if (Supported... check you can build against teh latest API
The problem is that it tells me the method doesn't exist. Even when using reflection, it still says it doesn't exist. It only "exists" when I use api-version: 1.21.5
check this
correct. You put the earliest version you want to use in the Plugin.yml
BUT you build against the latest
So you would have 1.16 in your plugin.yml but in your pom you would use 1.21
then hide any method calls that are not in 1.16 behind a Supported check before calling
that would cause more issues than it is worth
you'll accidentally call methods that have been moved around and it'll break ABI
It doesn't work. It's not about how I compile it
moved methods?
it should work fine with reflection
how have you tried calling it?
xD
that ius how you do it using a simple check
the code only runs IF the method is found
It doesn't make sense to check it since the module is specifically for that version. The module is never used or started if it's not 1.21.5
you also may not want to reference the Cow class directly
let me try it myself and I'll get back to you
ty
This didn't cause an error (I know it's wrong), but I think it would be crazy to use so much reflection just to access RegistryAware and get the key
what is this even for
why are you saving the cow variant somewhere
One simply does not question the Cowherd of his intentions
xD
This worked. I guess that not using absolutely anything from 1.21.5 allows me to use a different api-version
that doesn't answer my question though
But using this is horrible lol
To spawn a similar cow later
Do you really need the variant, and not just a reference to the cow, depending on the version that reference would hold different data
if all you need from the entity is the variant, just getting and storing the variant is generally easier than referencing the entity, as entity references may go stale or invalid over time and that requires additional logic to be dealt with
Yes but hes also after a method that will work universally.
Even before variants existed
as I have said before, it's generally easier to just make a different artifact which has a plugin.yml with a different API version
i'm not sure if having an entity reference would help here for version compatibility
i suppose you could use nms to clone the entity
but then you're using nms
paper does have methods for serializing/spawning entities from a byte[], but that also persists the uuid so that won't work
spigot has those too
a jerryrig approach that comes to mind is to use the structures api to save the cow into a structure, and then paste the structure in whenever you need a new cow; but this will clone not just the variant, but health and custom name and other metadata as well
oh nevermind, that PR was never accepted
that seems like a really complex way to just avoid having another artifact lol
it's 🤡 for sure
ideally spigot would let you avoid defining a set api version or be more granular as to which packages/modules are using that API version
the latter is less likely to be implemented but the former could be possible, given anyone who actually wants to deal with that
just have Spigot assume you are using the latest API version available
does the api version even do anything? iirc it just causes materials to get remapped and other bytecode nonsense like that if it's absent or < 1.13
it also hides API that isn't available in the given API version apparently
so if you try to use 1.21.5 API with 1.16 api-version, it'll just not work even if you are in a 1.21.5 server
i wonder if there is some mistake here or if paper has changed it to not do that
Paper doesn't support anything that isn't latest so I doubt it
because i recall it being said that 1.13 or 1.14 api version makes things work on everything; and most of my plugins have it set to 1.13 and work fine on a 1.21.4 runtime
but it is weird behavior, I'll give you that
they work fine because you're using 1.14-only API
definitely am not
well then I have no idea honestly, it might be something very specific to classes like the Cow one which have methods from interfaces that do not exist in older versions
yeah no it doesn't make sense, unless the api version stuff is actively messing with the classloader to hide the methods that don't exist there
given that Paper and Spigot use different stuff for remapping, I wouldn't be surprised if they have different behavior also
scrolling up it seems like reflection really can't find the members at runtime, so barring nonsense like accidentally running a 1.20 server or something it probably does hide them
seems like a paper diff but god only knows
Paper disables Commodore which I believe is what handles part of this stuff so, yeah
one can only imagine
i never did like api-version to begin with
personally i think any and all bytecode remapping nonsense is nonsense
it is nonsense, but it is necessary non-sense
though i will begrudgingly tolerate mojang-mapping/reobf things at runtime
well in the case of the cow, the new stuff is in AbstractCow which can have different/missing methods in older versions, you can't load the same class from the same package so one of them has to give, in this case it would make sense the older version is loaded if you specify a lower api version
the spigot jar bundles older versions of api classes?
where is it loading the older abstractcow class from then
see this is why remapping nonsense is nonsense
you can't make any kind of assumptions about the runtime
"what is happening?"
"i don't know, something is changing this shit into something else"
or maybe it's a bug?
who knows
it could technically do it on the fly, not exactly sure how spigot specifically implements that older api stuff legacy stuff. I wish it was removed as I don't see it being useful at all
https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/browse/src/main/java/org/bukkit/craftbukkit/util/ApiVersion.java#23 there is a specific remapping for AbstractCow
ah I see now, so if the api version is below that, it simply won't load it
how ironic the person has issues with that class though
absolute nonsense
rather it just renames it from Cow to AbstractCow apparently
Map<String, String> renames = new HashMap<>(RENAMES);
if (pluginVersion.isOlderThan(ApiVersion.ABSTRACT_COW)) {
renames.put("org/bukkit/entity/Cow", "org/bukkit/entity/AbstractCow");
}
so if api-version is less than 1.21.5, it renames Cow to AbstractCow? That doesn't make sense to me
or is it the other way around
wouldn't make sense if it was the other way around, however then what happens to all the methods though if that is the case?
We do what
do you not?
We do not
do we do this abstract cow remapping nonsense
Oh I must have misremembered then
It is off for paper-plugin.yml, that might be what you aare thinking of
makes sense
I believe this specific remapping for Cow -> AbstractCow is nonsense but I can't quite put my finger on it since I don't want to read code that uses ASM
Well, in 1.21.5 Cow became AbstractCow kinda and the new Cow type is like "NormalCow"
issue basically being, prior you could store a MushroomCow in a Cow
1.21.5 broke that
So plugins coming in from 1.21.4 are remapped to consider all cows abstract cows in 1.21.5 terms
the couple of places in the API that consume concrete "normal cow", e.g. spawn() map AbstractCow back onto Cow in 1.21.5
I see, so it isn't non-sense, at the very least
it just makes using reflection on it annoying
What is the usecase for reflection o.O xD
can't we just have things break normally instead of doing these remappings that make them break in unexpected and arcane ways
Yea, you do that by setting your api-version to 1.21.5
lol
they wanted to get the cow variant, but they couldn't do that since they were using api-version 1.16 or whatever
Yea I mean, gg lol
can i set it to LATEST so i don't have to think about it
annoying you have to even set api version to begin with
would be a fun addition
Yea, sadly the jar does not tell you what version of the api you compiled against lol
a latest would be kinda nice tho, a "just don't rewrite, I'll deal with this myself" kinda bit
api-version: just trust me bro
can we implement this pretty please
i suppose we could set up some gradle/maven resource expansion config to replace it in plugin.yml with the major version from the build script
Yea, I think that is somewhere at least in the paper pipeline for this
api-version: random
🔥🗣️ 🦁
I suppose whenever I get around to rewritting cb/spigot I will just remove a lot of this api versioning stuff

Yea, that is what paper plugins do, it is pretty nice
I am a fan of, if it breaks it breaks and whoever created it should fix it
not, lets try to keep these running
no more Initializing legacy Material support when you forget api version
i'll try paper plugins sooner or later
it just irks me how they're not reloadable, or are they
you can make anything reloadable if you really want

you just have to decouple your logic from the plugin lifecycle
for the rest, hotswapping it is
yeeeeah i don't uh really want to start fucking with custom classloading, considering all of the nonsense that the paper plugin classloaders also do that i'd have to account for
you don't necessarily have to
if you make every single bit of your logic data, and then create a human-readable format for that data
you could just store everything in files, and you can reload files
yeah let me just like write my plugin in python and then interpret it from my javaplugin
Skript be like
tbh that's the only thing I like about them, they're very easily reloadable
other than that, I'd have wished they decided on a stricter language
come to think of it, what's the current thing for running javascript from java
did nashorn die?
you just don't run javascript from java
people will tell you Graal's Polyglot API but nobody actually spends time dealing with that bs
it is just not worth it
how about uh compiling java source at runtime and then loading the classes
it'd be easier to run node in a different process and communicate through IPC or whatever
that's doable
I was actually thinking of making a plugin for this
and to think javascript cross compatibility used to be a major selling point
SingleFilePlugins
how far we've fallen
javascript is a no-go in the jvm but python on the other hand, is doable
same with ruby
unfortunately i detest python
since jython and jruby exist
they boldly claim to be faster than normal golang
which wouldn't surprise me, the JVM is very fast
you can always run these things externally
do this and i'll steal it and give you a free star on your repo
well, compiling and loading on the go is really not that hard
the hard part will be handling clashes in path/class names
it isn't hard, just annoying to do properly
i'm sure i could figure it out but it'd probably end up consuming a bit more time than i have on my hands
I'll try to make a half-baked version later
and i'd rather get to the fun part rather than have to fiddle with the underlying system
if I get that to work, then I might even publish it on spigotmc
my first public resource
I'll make it source-available
well, you would just invoke the compiler from a plugin which you would need to test if you have perms to do this, otherwise if you don't the only solution is to have your own compiler built in I guess which would indeed be a real pain lmao
my license will be "you can copy my code, but you ought to buy me a coffee later down the road if it ends up being useful to you"
as for loading classes you just use the classloader like what spigot and everything else already does 😛
What do people use for commands these days?
still the built in poopstick that is bukkit commands or are there decent frameworks? I'm not a big fan of Cloud
ACF also seems on life support
personally i find them all overengineered and not worth the effort
well i like them for complex command structures
i just register my root command with bukkit and then implement subcommands and parameters as a nested tree structure using hashmaps
it's a little bit of boilerplate i suppose but straight forward and flexible
and you can always bail out and rawdog it with plain old java code, unlike in a framework where you tend to have to bend over backwards for any special case that doesn't fit what the framework expects
do you have an use for them, though
chances are you'll be creating complex command structures for the sake of it, not necessarily because you need it
lots of plugins want something fancy when in reality, the less commands you have, the better
well i like giving players the option to edit all config options through commands. And usually thats a lot easier with generics and parsing than doing them all by hand
my personal line is that if it goes past 3 arguments, I should change the way the user interacts with it
despair
listing worlds, ignoring worlds that are already in the list etc
famous last words
looks at luckperms commands
I once saw the JVM straight up outperform C and that still baffles me
that's super convenient right
and everyone likes guis right
can't go wrong with a gui right
luckperms has the website interface though
Yea, but the commands aren't hard. :p
not ideal since it doesn't interface that well with minecraft but at the very least it is better than the commands
i dont dislike gui stuff but damn do i hate minecraft gui stuff
they are hard, I never quite understood contexts
Contexts are easy, wym?
LuckPerms is considerably harder than say, PermissionsEx
it supports more features, sure. But at the cost of complexity
the basics are straight forward enough and roughly comparable to pex
even the command structure is quite similar
/lp group default permission set poop.fart
it is nowadays, it used to be a lot worse before and that is the impression that stuck with me
i find luckperms to be quite intuitive tbh
i profoundly dislike the api but the command/user side is intuitive enough yeah
I remember back when you had to explicitly set permissions to true or false, since there was no default
annoying ass UX
i remember when you had to edit the permissions files
love me some yaml
I will prefer a yaml configuration any day over a command, though
just make your configuration reloadable
to be honest i still prefer editing pex permissions.yml over the luckperms web ui
Sounds like skill issues all around here. smh
i havent ran my own server in years so i dont really remember
we're all old people
Define old
people who have ran servers probably back in 1.8 and haven't really tried to adapt to the new stuff
everything is nice and clean and in front of your face and you don't have to scroll through menus and submenus and scrollboxes and fiddle with text fields
you see the entire group definition at once
now granted the fact that the same file also has 10,000 users in it does make it a bit annoying
the luckperms web UI could use some UX improvements, but it's better than not having it at least
situationally better than commands for sure
though for single edits i still use commands
It would be cool if other plugins could have web interfaces.
Need to start a new trend.
please no
Options are nice
yeeeah i'll hard pass on that
LuckPerms has one in spite of its complexity
and barely any plugins reach that level of complexity
unless it comes down to a web UI for editing every single plugin configuration, but that would be a hard ask
i would take a web ui over an ingame chest menu config gui any day of the week but the mvp is and always fill be a readable, well structured plaintext file in yaml or json or fucking toml if you're a hippie nerd
then there's that one dude using HOCON for comments in JSON
i swear velocity using toml for the configs is some kind of reactionary meta statement
they just jumped on the hype-train, rust made the format popular
we're DIFFERENT from bungee I SWEAR
to this day I haven't ever run a velocity instance myself, so I will never know what all the hype is about
it's quite alright
bungee seemed enough for me at the time, it probably still is for most people
and the toml nonsense is tolerable as well though it is marginally irritating
it's the one thing I dislike about Paper, if anything. They don't really tell you why it's better, you're just expected to know
my number one gripe with velocity is that it doesn't bundle the bukkit config system so i need to use some massive bloated library or rawdog it with snakeyaml or gson
i usually have both the bukkit and the proxy classes in the same artifact and it'd be nice to be able to share the config system without having to abstract it to all hell
people seem to use Configurate nowadays, even though it is fairly limiting imo
so what i've ended up doing in recent times is just bundling the fucking bukkit config classes into the resources directory so they get loaded from the jar on velocity
it's neat i suppose but yeah limiting
i generally refuse to use most frameworks unless i can bail out in the middle of it and fallback to plain old java to handle a special case
i.e. give it to me as json and i'll parse it
just use java Properties 🤑
have the config in command line parameters
maven be like
i guess it is situationally useful to be able to override the config from command line
no comment on that, I've been burned too many times
i wonder if anyone uses xml for their plugin config 🤡
now that's the kind of crazy I am all about
i know InventoryFramework has XML support
Configurate supports HOCON and XML but not TOML kek, kind of ironic
I remember them talking about it when they were implementing that
XML does make a nice language if you use more attributes and less sections
toml my beloved
murder
the java parsers are kind of bad
notepad++ doesn't have highlighting for it
or maybe it's because i haven't updated it in 10 years
either way that means it's bad
I haven't heard of notepad++ in years
at some point I tried Sublime and could never go back
eh tomlj or w/e it's called is decent
neverheard
I used it for the toml support in my game engine
sounds like zoomer nonsense to me
Sublime is newer than Notepad++ but older than vscode
I do something similar. Always funny when people complain about boilerplate code forgetting IDE's are advanced enough to take care of most of that for you if you just set it up to do so
nobody likes to invest in tooling
everyone wants abstractions, they make you feel smart
not sure if its investing in tooling but its generally a feature already built into the IDE
yeah but why do it yourself when someone else already did it for you
creating templates is a form of investment in tooling
lol I really need to keep working on my config API ```kt
public object ExampleConfig : Configuration("toml", "config") {
public val string: String by string() or "hello world"
public object NestedSection : Section("section") {
public val num: Int by int() or -1
}
}
the issue with it is mostly that these templates aren't easily transferable to other environment, so you're locked in to whatever you're using
usually not an issue in the Java world where one picks an IDE and swears by it though
i liked configurate but i got banned from the sponge discord a couple years ago so thats fun
what is the by nonsense
I don't understand that operator
it's a delegated property
Hey, it's me again. Is there another way to get more than just the exposed ones? So also dynamically customized permissions like with LuckPerms?
I looked into the LuckPerms command and there's way too much stuff in there.
val minecraft_version: String by project
why does this read from the gradle.properties file
I would've never guessed
because Project implements delegation operators for properties
it's fancy but I don't love it
just use LuckPerms API
completely lost in the sauce
I… am not sure. I would’ve imagined that dynamic permissions populate the set at runtime
Well, I can say that about every thing. Then I wouldn't need to make my plugin xd
most plugins will just check if permission do stuff and not necessarily register their permissions so you'll just have to deal with that
i think luckperms keeps track of those checks (since they're delegated to it) and adds them to some set of known/cached permissions
since stuff that isn't registered but is checked for shows up in lp tabcompletes
so, yeah
use LuckPerms API
you could try maybe Vault but I doubt it will give you what you want
just the thing is that you won't see them through the api before the check is made for the first time, which, god only knows when that is
Nah, that would be boring. I'll make my own logic then or leave it as it is with #getPermissions
just scan every plugin for hasPermission checks 🤑
well I wasn't just referring to templates. My ide lets me store code snippets in a library kind of thing
not totally infeasible with asm i suppose, although programmatically generated perm strings are going to be quite ass
it'll cover 80% of the cases, but fail with plugins which use some fancy abstractions for their permissions
i.e. I saw plugins using an enum for the permissions and then checking capabilities or what not, so they never directly call hasPermission
maps also implement this which I love
things like the essentials multiple homes permission nodes, which are defined in the essx config
perhaps uh doing what luckperms does, i.e. keeping track of checks, but also persisting them across sessions would be easier and more robust
with the caveat that you'll see permissions used by plugins uninstalled since
walk the stack trace of every check and get the calling plugin and only load the persisted perm strings from that plugin if it's loaded 🤡
iirc all you have to do is implement PermissibleBase and then go from there
i wish we had invented namespaces in time to use them for the permissions system
we kinda sorta use namespaces already but only by convention
me when I have 5 plugins using the home namespace
is there any way i can access the vanilla cave generator via nms and get it to generate a singular cave starting from some fixed location?
you could create a custom chunk generator that just delegates to vanilla
and then force that chunk to regen with that generator
caves are usually multi-chunk though no?
and i only want a single cave, nothing else
i imagine it would be quite resource intensive if i regenerate entire chunks
(i could just check where the cave branches and regen those chunks as well)
ig i could just copy the nms code
but sounds like that would take a while in the latest version considering all of the new cave features
It’s mostly done with noise layers
argh sounds like a lot of work tbh
it shouldn't be all that intensive, I'd just use NMS to generate the cave wherever you want
limiting it to only certain chunks might probe annoying but should be doable
for my game i want to generate a single cave (preferably of which i can adjust the size in code) and then teleport the player into that cave (as a sort of mining trip)
I'd just have a world which is just caves and teleport the player there
when you start running out of caves, create a new world
not that it'd happen anytime soon
it should work fine if you pregen a wide range with Chunky or something
thats the point
it wouldn't be any more intensive than keeping a normal survival world
its more memory to trade for performance
that will eventually lead to the same outcome
but pregeneration skips the part where it feels laggy
does buildtools place the decompiled/deobfuscated server code anywhere?
in the same directory it runs
its in the buildtools work directory
just open the folder where you have the BuildTools jar inside of your IDE, and you can cross-reference the craft/bukkit/nms layer that way
the nms cave carvers use noise which means it isn't really trivial to start a cave where you want it to start
you'd essentially have to find a position in the noise where a cave would start and then offset the noise so that that spot is where you want it to start in the world
could just have some kind of template cave and base off that for some randomization
if you want to go for efficiency in making the most of a world for caves
you could just generate the entire chunk as blocks
there's a vanilla world gen template for a world of caves
and then add some bedrock that is large enough where you couldn't see other players
probably could stack 3 caves this way
so you could just generate it on single player and move it to the server afterwards
getting a vanilla-looking cave with your own "carver" could probably be done by assigning a few points where you want the cave to go and then running along a bezier curve of those and adjusting the size of the carver as you go so it tapers off at the ends
this is iirc roughly what the vanilla generator does, except the curve is defined as the intersection of some noise layers or something
of course that leaves all of the blockpopulation and decoration and other nonsense to you so not exactly ideal unless you want a super basic vanilla cave
sure
and also preferably control their length/size
But just 1 cave like a spaghetti or a cave system
if it is a single cave then it'll abruptly end at some corner which isn't ideal
I think its very annoying, traditional way is noise but you don't have control on the overall shape, its noise
you could code smoothing logic but it is all very annoying
i tried using simplex worms but just got god awful looking caves
Simplex worms
hence why I just recommend generating a world which is just caves
then teleporting the player there
you won't have to deal with generation that way
simplex worm is a modified simplex noise for caves
It’s a worm shaped cave made with simplex noise
i think the more common name is perlin worms
or well
its perlin worms but with simple noise
To generate caves you can just apply threshold to a 3D simplex noise
that's what simplex worm is, essentially
well i do have control but they look awful
Unoptimized way : take all your points, and generate a shit ton of noise until those three points are in cave AHAHAHA
2^n optimized
usually generation isn't all that important for caves, decorations are
if you don't want to dynamically generate the cave itself but rather the tunnels then all you need to do is make enough tunnel designs and then stitch them together in a dynamic fashion like a maze
for my game i want to generate a single cave (preferably of which i can adjust the size in code) and then teleport the player into that cave (as a sort of mining trip)
so, as long as you manage to make some block populators that resemble minecraft's decorations, then it is going to look pretty good
Yes wave function collapse
that would also work
wave function collapse is overkill
im awful at building though
💀
I did it for a map generation plugin. It generated me nice maze like labyrinth
lol
Wfc is basically sudoku
but the key here is it would work
the nuclear option is still an option as they say
If wfc is working, then good. Maybe what, you generate a map once in a while not every tick
my recommendation is that the less you touch generation the better
Bro
it's just very annoying to deal with
I touched generation
well it seems they don't really need to generate anything persay
I spent 1 whole week trying to implement bilerp
those look like caves to me
they could accomplish this with the randomizing of templates and just ensuring you are not generating a tunnel into the side of a wall or something lmao
well, the old ones, not the new ones
yeah this is vanilla 1.21.5
i just flew around in spectator to find a good one
i want to generate caves like this
but why are you so stuck on generating them, I don't understand
Use noise
just use a normal world instead, forget about generating it yourself
or do what frost said and just convert some random cave to a structure and paste that in random ways
wonder if there is a way to get the generator settings for caves
you could use the custom world gen template for it
let me see if I can find it
how can I cancel the book and quil gui opening when clicking a book as I did canceled the interaction event but it didnt work
protected static final NoiseSettings CAVES_NOISE_SETTINGS = create(-64, 192, 1, 2);
public static NoiseSettings create(int minY, int height, int noiseSizeHorizontal, int noiseSizeVertical) {
NoiseSettings noiseSettings = new NoiseSettings(minY, height, noiseSizeHorizontal, noiseSizeVertical);
guardY(noiseSettings).error().ifPresent(error -> {
throw new IllegalStateException(error.message());
});
return noiseSettings;
}
private static DataResult<NoiseSettings> guardY(NoiseSettings settings) {
if (settings.minY() + settings.height() > DimensionType.MAX_Y + 1) {
return DataResult.error(() -> "min_y + height cannot be higher than: " + (DimensionType.MAX_Y + 1));
} else if (settings.height() % 16 != 0) {
return DataResult.error(() -> "height has to be a multiple of 16");
} else {
return settings.minY() % 16 != 0 ? DataResult.error(() -> "min_y has to be a multiple of 16") : DataResult.success(settings);
}
}
which is then used like this for the caves world gen:
private static NoiseGeneratorSettings caves(BootstrapContext<?> context) {
return new NoiseGeneratorSettings(
NoiseSettings.CAVES_NOISE_SETTINGS,
Blocks.STONE.defaultBlockState(),
Blocks.WATER.defaultBlockState(),
NoiseRouterData.caves(context.lookup(Registries.DENSITY_FUNCTION), context.lookup(Registries.NOISE)),
SurfaceRuleData.overworldLike(false, true, true),
List.of(),
32,
false,
false,
false,
true
);
}
do note those are parchment mappings, so if you use anything else you'll have to translate
thats fine
the code makes much more sense when you can see the parameter names, should have taken screenshots lol
hi, can someone help me with the BLOCK_INTERACTION_RANGE attribute? When logging the Total Value of the attribute after adding the modifier it shows the correct value but it shows no effect for the player. Any ideas?
client and server version 1.21.4
If I had to guess, it’s handled by the client so I’d assume this wouldn’t actually affect the interaction range
hm? Are you manually applying effects for a tool? Why not add the attribute modifiers to the item directly?
the effect needs to be added as a player attribute and cant be bound to a item, in my case its only active if a player holds their prison pickaxe
i "found" the issue in the meantime. a simple server restart did the trick, no idea why that was needed 🤷♂️
I don't see anything that can't be bound to an item
that sort of kind of uh sounds like its bound to their prison pickaxe
it extends the players interaction range when the prison pickaxe is in his main hand
that's what bound to an item means, yes?
they can?
yes
all of them or only specific ones?
add an attribute modifier to the item meta
i don't recall any that wouldn't work, except of course the ones that aren't applicable to a player at all
e.g. you can put an armor modifier on a pickaxe
the client and server look at all equipped slots and collate all the attribute modifiers on them together
tbh I wouldn't be supprised if you could
this is what attribute uuids, more recently namespaced keys, are for; if two or more slots have an attribute modifier with the same id, only one of them is included in the calculation, so they don't stack
you can yes
wait I read that as can't 💀
because player does have the armor attribute
but you can't like add a uh zombie reinforcement chance attribute, i don't think
does scale also increase jump height
