#help-development
1 messages · Page 1343 of 1
yes but i would like know the difference between tooltip display and hidden components
item.setData(DataComponentTypes.TOOLTIP_DISPLAY, TooltipDisplay.tooltipDisplay().addHiddenComponents(DataComponentTypes.ENCHANTMENTS).build());
i think im doing well
Seems pretty straightforward.
Tooltip display is the parent for all data that is displayed in it.
Enchantments, Damage, Unbreakable, Lore, Trims, etc
Hidden components are what you want to hide from that list.
Certain items will be different since they have different components to begin with, but it's just hiding what you don't want to show.
Yes
I believe everything on items is a component now (at least for vanilla), but don't quote me on that
Yes
I didn't understand 100%, but am I doing it right?
Couldn't tell you. I don't use paper, but just reading that and taking from context, it looks like how you would set it to hide all enchants on the tooltip.
u run a server with spigot?
Yes and no.
I don't run a server, but I like contributing to spigot. So I need to run them for testing.
I give a item with unbreaking 1 and then do tooltip data thing. Perhaps if the person adds another enchantment, it will remain hidden
oh i see
Try it and see
Yes it will hide all enchantments
I don't get it, is that not what you wanted?
Are you trying to hide all enchantments or just one specific enchantment?
I just want to hide an enchantment, and then if someone applies the enchantment, it will appear. Perhaps because this is complex (because I have to listen to listeners), it might be easier to add an enchantment that can't be applied using tools like aqua_affinity, for example
Why do you want to hide just the one
i want do item glow
There’s a component for that
this maybe item.setData(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true);
enchantment_glint_override moment
Is it possible to prevent an item from being renamed using components or something similar?
or need use listeners?
Probably listeners
ItemEnchantments.Builder enchantsBuilder = ItemEnchantments.itemEnchantments()
.add(Enchantment.EFFICIENCY, 5)
.add(Enchantment.UNBREAKING, 3)
.add(Enchantment.MENDING, 1);
if (id == AmethystItemId.TREE_CHOPPER) {
enchantsBuilder.add(Enchantment.SILK_TOUCH, 1);
}
item.setData(DataComponentTypes.ENCHANTMENTS, enchantsBuilder.build());
Enchantments are applied without calling the build call. Should I keep the build call?
I don't think it matters
Yeah it just calls build for you
oh i see
Doesn't setting the system line ending property work? I'm sure does from command line but idk if from within pom.xml properties
line.separator or whatever
@Override
public EconomyResponse withdrawPlayer(OfflinePlayer player, double amount) {
return withdrawPlayer(player.getName(), amount);
}
The vault uses the player name for this. Isn't that dangerous?
but this support offlineplayer
Let's say a premium player with nickname A puts an item up for auction. Then they change their nickname to B, and a premium player registers nickname A. Another player buys the item initially from A, and I do a vault#depositMoney to player A because A sold the item. The wrong player receives the money, and player B, upon entering the server for the first time with the new name, the item is sold and is left without the money (B sold the item because I assume the auctionhouse plugin uses the UUID)
that's a default implementation that can be overridden by the economy provider, i think
it's impossible to say without me actually looking up the class because i have no idea what you sent an excerpt of
but the answer basically is "depends"
It's the AbstractEconomy class
It's up to the economy plugin implementation to decide what happens
oh alr
Vault is just a bridge. It may or may not actually use the player name when you pass the offline player instance
I didn't test that tbh. Mainly because I couldn't find a way to set environment variables within maven.
I can retest to see to confirm it works as intended via the command line, but I don't know of a way to set environment variables through maven.
Unless you were planning on adding it to BuildTools?
Idk, that feels kinda hacky to me now that I think about it
MAVEN_OPTS i think?
Yea, it's MAVEN_OPTS, but how can you set it within maven? Specifcally through one of its plugins.
So, this was weird.
Running mvn clean package -Dline.separator=\n in the IDE still results in differences.
Setting the env var fixed the issues with the diff that it created, but still has differences in the pom.properties.
[02:11:10 WARN]: Couldn't look up profile properties for 5fd75f1a-4f6f-354e-b204-6affa1df39bd
com.mojang.authlib.exceptions.MinecraftClientHttpException: Status: 403
at com.mojang.authlib.minecraft.client.MinecraftClient.readInputStream(MinecraftClient.java:100) ~[authlib-7.0.61.jar:?]
at com.mojang.authlib.minecraft.client.MinecraftClient.get(MinecraftClient.java:56) ~[authlib-7.0.61.jar:?]
at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService.fetchProfileUncached(YggdrasilMinecraftSessionService.java:197) ~[authlib-7.0.61.jar:?]
at com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService.fetchProfile(YggdrasilMinecraftSessionService.java:167) ~[authlib-7.0.61.jar:?]
at com.destroystokyo.paper.profile.PaperMinecraftSessionService.fetchProfile(PaperMinecraftSessionService.java:40) ~[paper-1.21.11.jar:1.21.11-131-6d5b910]
at com.destroystokyo.paper.profile.CraftPlayerProfile.complete(CraftPlayerProfile.java:289) ~[paper-1.21.11.jar:1.21.11-131-6d5b910]
at com.destroystokyo.paper.profile.CraftPlayerProfile.complete(CraftPlayerProfile.java:278) ~[paper-1.21.11.jar:1.21.11-131-6d5b910]
at net.minecraft.server.network.ServerLoginPacketListenerImpl.callPlayerPreLoginEvents(ServerLoginPacketListenerImpl.java:329) ~[paper-1.21.11.jar:1.21.11-131-6d5b910]
at net.minecraft.server.network.ServerLoginPacketListenerImpl.lambda$handleCustomQueryPacket0$2(ServerLoginPacketListenerImpl.java:406) ~[paper-1.21.11.jar:1.21.11-131-6d5b910]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090) ~[?:?]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614) ~[?:?]
at java.base/java.lang.Thread.run(Thread.java:1474) ~[?:?]
should me worries?
yes you are in danger
?whereami is hunting a lot today
but looks like a rate limit, did you perform many calls?
Shouldn’t that be http 429
depends, I heard that mojang blocks your IP for a certain time, which would explain the 403
Yea, it doesn't seem to matter what I do here, I'm still getting differences in the pom.properties files.
- Running
mvn clean package -Dline.separator=\nin the IDE - Setting the
MAVEN_OPTSenvironment variable - Setting
<line.separator>in the custom pom properties
It is just not affecting the file for whatever reason.
I'm making a plugin for a minecraft smp thats starting soon, and I'm basically making mythic items (such as the dragon egg, which increases your health from 10 hearts to 15 hearts) and I was wondering if there was a way to check the inventories of players that are offline. I need a command (for admins) that checks who holds the dragon egg and other mythics (like the only netherite set) and sees if these items have been destroyed, and I need help 🙁
i recommend using https://github.com/Jikoo/OpenInv as a dependency and using its api instead of rolling your own solution
100%
or maybe explain what you actually need help with
aside from "write the plugin for me"
Thru what can I achieve to make a clickable wall like as shown on the image, with custom mob icons, fonts, progress et cetera?
that is a bunch of item frames with custom map rasters drawn on them for the mob icons and fonts; the clickability is done by listening to the player interact event and raytracing/projecting the interaction point onto the image, then handling it as desired
the arrow icon on the right looks too high resolution to be a map raster, so i suspect it's a text display with some unicode arrow glyph, or a custom font glyph from a server resourcepack
https://github.com/MinceraftMC/MapEngine is a good starting point
Am I using try-finally correctly? (prob not)
I want to ensure that completablefuture doesn't remain stagnant forever
you are not, but that method is doing way too much to be able to understand it
infinite nested futures
you should use composeAsync or whatever it is
basically any time you're creating a future within a future you're already off-track
that would still end up with a gigantic method doing too much, they need to rework that in order for the responsibilities of each callback there to be more clear
personally i prefer virtual threads
i don't know, the method is doing like 5 things with maybe 20 lines of actual business code
the rest of it is try-catch-finally and future/scheduler noise
public CompletableFuture<Boolean> addPlayer(UUID playerUuid, String name) {
if (isFull(1) || playerNameByUuid.containsKey(playerUuid)) {
return CompletableFuture.completedFuture(false);
}
if (!tryReserveSlot(playerUuid)) {
return CompletableFuture.completedFuture(false);
}
return checkExtraSlots(ownerUuid)
.thenComposeAsync(
extraSlots -> persistMember(playerUuid, name, extraSlots),
Bukkit.getScheduler().getMainThreadExecutor(BoxPlugin.plugin)
)
.thenCompose(pos -> publishAndApplyLocally(playerUuid, name, pos))
.exceptionally(ex -> {
BoxPlugin.plugin.getLogger().log(Level.SEVERE, "Error adding player " + playerUuid, ex);
rollback(playerUuid);
return false;
});
}
if the word was sane this would basically be it
though I don't love that code, at least it is less of a burden in my eyes
much better, though i might propagate the exception to the caller
it's always a bit troublesome with futures to decide where to handle your exceptions
but then you can't handle rollback the add player action, it's annoying yeah
you could rethrow it in exceptionally after handling it 🤡
if that method was made to return the added value then maybe it'd be better to propagate the exception
or, more reasonably, branch off a separate future that you don't return which will handle the rollback
public CompletableFuture<Boolean> addPlayer(UUID playerUuid, String name) {
if (isFull(1) || playerNameByUuid.containsKey(playerUuid)) {
return CompletableFuture.completedFuture(false);
}
if (!tryReserveSlot(playerUuid)) {
return CompletableFuture.completedFuture(false);
}
var future = checkExtraSlots(ownerUuid)
.thenComposeAsync(
extraSlots -> persistMember(playerUuid, name, extraSlots),
Bukkit.getScheduler().getMainThreadExecutor(BoxPlugin.plugin)
)
.thenCompose(pos -> publishAndApplyLocally(playerUuid, name, pos));
future.exceptionally(ex -> {
BoxPlugin.plugin.getLogger().log(Level.SEVERE, "Error adding player " + playerUuid, ex);
rollback(playerUuid);
return false;
});
return future;
}
I guess this works
not sure how to feel about it
my preferred method with coordinating threaded behavior like this is by spawning a virtual thread and joining other futures
this is pretty clean as-is since it doesn't need any flow control within the futures
how do you deal with stuff like that "Villager was squished too much"
[22:50:33 INFO]: Villager Villager['Villager'/73656, uuid='24215612-f89b-4df1-8acc-376e543dac05', l='ServerLevel[world]', x=-2483.30, y=44.00, z=-3207.12, cpos=[-156, -201], tl=30703, v=true] died, message: 'Villager was squished too much'```
how can you prevent from villagers being spawned in the first place. isnt it kind of tricky? spawn limit per chunk for entity is a mess.. because there are multiple ways to spawn them.. and for some ways its weird if you limit it but they all fall in the same "reason"
The method only adds a player to an "island," but I need to update the database, Redis, and local cache
The problem is that logger#log might throw an exception. Therefore, the rollback isn't executed. Should I not be worried about this?
if logging throws an exception you're cooked
So the programmer simply ignores it in those situations?
https://pastes.dev/UYOrXw86Zd For example, if redisExecutor#submit throws an exception, the future is never completed
So I don't have to worry about it then?
any sane logging impl wouldn't throw
for JUL, it reports to ErrorManager iirc
not that it cannot happen, but it shouldn't happen under normal circumstances
what about this?
this is why instead of completing futures manually, you use the factory methods and return from them
if anything throws within a future, the future is completed exceptionally
in this case, instead of passing a task to BoxPlugin.plugin.getRedisExecutor() which manually completes a future at the end, use the redis executor as an executor for an async future
I think the issue is that you're trying to rollback at every stage of the chain
and simply perform the task within the future
if you're using futures and propagating exceptions properly, you should just commit/rollback at call-site
i see
mfw when the logger exception causes the logger logger to throw, so logger logger logger has to step in
I think there's a chinese proverb about this
It is in fact loggers all the way down
and then you have paper adventure which makes player.sendMessage throw if it sees a §
which, given how frequently that occurs in legacy codebases and configs, totally never happens
i love lying on the internet
and has totally not resulted in item duplication issues or anything because inventory.takeShit runs after a player.sendMessage in 1000 places of random business code
sendRichMessage*
on really both was ok because this method is called on a CompletableFuture with exceptionally block
so yea
but i think 2nd is better
that's better
now also use the bukkit executor instead of scheduling a task with try catch and manual future completion in it
I thought it was minimessage that throws in that situation
same principle as with the redis executor
At least that’s where I’ve encountered it
but this can throw too?
it does, but sendRichMessage delegates to it
doesn't matter
u say to do that bc is more clear?
try catch manual complete = bad
i see
use executor = good
the nag is at TextComponentImpl construction
but it is only enabled on test environments such as the ones generated by run-task, not by default
and it only prints it, doesn't throw
i think it might be minimessage or something, i don't remember the stack trace
https://pastes.dev/EfOR8zctiz very better
it does print a stack trace, but it doesn't throw 😛
37 to 16 lines
[13:15:05 ERROR]: Could not pass event TownyBuildEvent to SiegeWar v${project.version}
net.kyori.adventure.text.minimessage.internal.parser.ParsingExceptionImpl: Legacy formatting codes have been detected in a MiniMessage string - this is unsupported behaviour. Please refer to the Adventure documentation (https://docs.advntr.dev/) for more information.
it throws
at least on whatever version i'm on; i'm on some random paper build of 1.21.11
i wouldn't care if it didn't throw
^ this was me doing player.sendRichMessage with a string pulled from a config
but the config value had a § in it
so the event handler threw before it could check perms or cancel, and suddenly everyone was able to build in every town
another plugin had a similar issue except it sent a success message from a config in between giving crate reward items and consuming the crate key
which resulted in the key being infinitely reusable
very fun
sendRichMessage was supposed to be the super useful and friendly and convenient formatted message facility that legacy colorcode guys like me who liked the old concise color codes would migrate to
now i have to wrap every call of it in try catch ignore throwable
which is neither friendly nor convenient
i can't even run the strings through the minimessage legacy string parser, because that will escape the actual minimessage tags
https://github.com/PaperMC/adventure/pull/662 you can blame Linox for that, whoever they are
Implemented the nagging feature from API to MiniMessage. But because API wasn't a part of MiniMessage I put down a small method and used that.
fucking ajan
jesus christ
@rough sonnet
i swear i will fly to turkey and shit on his bed
the fact that you know is hilarious
we've collaborated on some projects
could just PR to adventure to see if they put the MM nag behind the same system property as the one in TextComponentImpl tbh
HAHAHAHAHAH
and make it an actual Nag, not a throwing exception
I think I got around that by leaving them as & codes, minimessage parsing, then converting that to legacy and then using translateAlternateColorCodes
Yes that’s very janky
I’m aware
I think you're not the first one to do that because I have a dejavu feeling about that solution
it is what it is
https://pastes.dev/fwiAbmHvOX If an exception occurs in Redis, the member is removed from the database, but Redis and the local cache retain it. How should I handle this?
BoxPlugin.plugin.getBoxService().removeMember(ownerUuid, playerUuid) is the database call
BoxPlugin.applyBoxListEntry() is the redis call
I'm more concerned about your project structure than mystical db failure
very old project
dont use redis I guess
or what you can do idk your structure behind is trying to change the relationship for the entities.. alternatively
but i need
to be fair I am also questioning the redis usage here lol
you got a bit too many layers tangled up there
It could happen that you need to refetch the parent entity to have the updated users, it's pretty weird whats happening there..
If you can provide an actual error message i believe it's easier to help you
thanks
i dont have an error message
Can you debug throug hthe lines ?
i just want do some good practices
ah
eee use my awesome database framework stuff https://github.com/JExcellence/JEHibernate
doesnt need redis, nothing, has caching and all u need 💀
I think because im dumb
😂
okay your plan is to remove something of that boxservice?
my plan is fix this code
You could also try to ask AI what's wrong there and how it could be improved
I mean i would need the error message in order to fix it..
it seems some error in your database query is happening
Can you debug live through the lines?
and check what's in variable ex?
if that doesnt work, go to the database request where removemember is happening and debug there through
sometimes database issues just get sucked up silently
Are you familiar with the Hypixel islands plugin? Does it need to query MySQL every time someone opens the menu of the islands it's added to?
No
You have it ideally inside a cache
a hashmap or something
wait i can show you how i did it in my oneblock system
But this is a multi server setup
Maintaining this in a local cache might be a difficult task
You should then handle it in a way where it should only be fetched once then on player join or something and work with it on that given server
What I did was keep this in Redis so that whenever someone wants to go to a friend's box, it's a query in Redis and not in MySQL. But I don't know if this is advantageous at all
Depending on the request and how many players you expect, but overall not targeting the db is mostly the better solution
The overhead of keeping this sync should be the cost of the person opening the menu
How could it get out of sync?
I think the best solution here would be to have local caching + redis pub
if you just update the cached version only
I didn't say that
and send it over to the db to update
ah nvm
thats how i find my island
public @NotNull CompletableFuture<Optional<Island>> findByOwnerAndRegionAsync(
@NotNull UUID owner, @NotNull RegionType regionType) {
return query()
.and("ownerUuid", owner.toString())
.and(FIELD_REGION_TYPE, regionType)
.firstAsync();
}
and before fetching it im checking if its inside the Cache if so use it otherwise fetch it.
im using Caffeine for that
maybe a alternative for you
you do that?
Could support it
but its orginally made just for one server
Because it has great performance, all islands will be on the same world
Well i think i'll do that
with multiple worlds depending on the size
I'm considering not using caching just for simplicity
Do what you prefer, i never used redis so can't really say anything about it
more like plebis
Who needs redis when you can encode the data into json and then email it between servers
Why email when you could carrier pigeon it
If the servers are on the same system you can just do memory mapping instead and just have all the servers use the same memory mapping.
Best part of that is that the OS maintains that so as long as it knows you are a retaining a descriptor for it and if your app crashes the OS will close it out for you after a period of time.
mfw it’s time to migrate to a containerised setup and the intern used memory mapping..
Anyne know a way to replicate this in 1.21.11?
hypickle does it by listening to player interact events and replacing the item in your hand with a sword with a rotated model
this is ass however because it is jittery and latency prone
you could perhaps try adding the blocks attacks data component on it, and then iirc there is a model predicate that allows you to use a different model for the item while it's "blocking" like a shield
i could be wrong, i can't find the list of all item predicates, the wiki is ass
Yeah this is something I tried out and I got the desired result
thanks
the fuck
i thought that they just use the component system that lets u set swords as blockable
although i guess that the client probably doesnt? have that specific animation anymore
there never was an animation, it was just a model swap
that is, the client would just change the rotation/translation of the model when holding rmb
that's still doable through the component system through the blocks attacks data component and item model predicates
i don't know why hypickle doesn't use it; they just replace the item in the player's hand with another using the same model+texture but different transformation
which makes it bob up and down with the "swap held item" animation each time, and since it's serverside it happens however many ms too late
i guess they don't care because their playerbase is mostly 1.8 pvp sweats anyway
hm maybe i'm talking about some other big server
i was there like once because someone invited me
but it definitely was a sword with a custom transform
Last I checked hypixel puts a shield in your offhand
Yes
not anymore
Though that one does use a resource pack
i don't remember which gamemode it was where i saw the sword
there was this big wooden platform with a big hole in the middle of it
i accidentally walked on a pressure plate and got blasted into oblivion 1000 blocks away
i know last i played skywars on 1.21 it had a normal blocking animation from 1.8 (aka shitty one that insta transitions between blocked and unblocked)
Modern versions do not
We use the blocking animation
consumable component use animation block :nodders:
something like that
I dunno. One of those two lol
No more shield, basically
Yeah it's still the consumable component
hax0ring
you should give it slime squish sound
just for funsies

I don't want that kind of party while I'm blocking
Woah. So culturally diverse, you are
yay
yo I'm making a plugin and i need help
basically I'm using the OpenInv plugin's api as a dependency to get the player's inventory, loop through it, see if I can find the dragon egg in his inventory (this is for offline players, its pretty simple for online players) and I'm not sure how to do this as there is no documentation that i can find for OpenInv's API
Can just take a look at the api module on github
You're mostly interested in the IOpenInv interface that's implemented by the plugin instance
it isn't very clearly indicated (and i have no idea what an ISpecialInventory is in practice), but i think the intended approach is to load an OfflinePlayer into a Player and then use the regular bukkit inventory methods on it
wha
@ancient plank
mrbreast
?ban 400934694843056140 bot/hacked acc
Done. That felt good.
why do i see these weird symbols?
btw im using putty and ssh into a vps
how can i avoid these issues in code?
Looks like the result of the colour characters
thank you
Yes
It is due to encoding on terminals. Terminals do not use utf8 by default where as mc is.
Just change the encoding and it should fix some problems
Putty for example will use ISO-8859-1 also known as latin-1
Then there is the issue of colors. Most terminals including putty only support 8 bit colors. Ironically I have a project that converts colors for console
cowors
edible swords 🤤
u can do that???
thats good to know ig
wait but like do u just do something like
for (OfflinePlayer offlinePlayer : offlinePlayers) {
Player player = new Player(offlinePlayer or something idk);
for (ItemStack item : player.getInventory().getContents() {
if (item.getType() == Material.DRAGON_EGG) {
player.getInventory.removeItem(item);
}
}
}```
im really new to java (just started learning java like a month ago lol) so im not very familiar with spigot api
hhhhhhh ok
that figures
then how would u even instantiate a player object thats offine 😭
thats the crazy part...
would it be a better use of my time to just use OpenInv
yes.
im trying to create a world, which works but when teleporting players to World#getSpawnLocation() it doesnt do anything
?nocode
It’s hard to answer a programming question without code
Oh no! You ran into a problem. But no worries, people are willing to help, but first they need to see your code. This is because otherwise, they would be providing help based on guesses instead of concrete knowledge. Whether it be a compile error, runtime error, or an unexpected output, I'm sure that if you were to provide code, you'd receive a quick solution.
i don't know if there is any apart from the javadoc comments in the source code itself: https://github.com/Jikoo/OpenInv/tree/master/api
e.g. on IOpenInv.java
/**
* Load a {@link Player} from an {@link OfflinePlayer}. If the user has not played before or the default world for
* the server is not loaded, this will return {@code null}.
*
* @param offline the {@code OfflinePlayer} to load a {@code Player} for
* @return the loaded {@code Player}
* @throws IllegalStateException if the server version is unsupported
*/
@Nullable Player loadPlayer(@NotNull final OfflinePlayer offline);
dont know why u deleted the teleport code screenshot, but getLocation() returns a copy of the location i believe
I mean the whole process is synchronous so world loading will be finished already by the time createWorld returns
i now know why it doesnt work
the player has passengers
and that isnt supported
is there a workaround?
also teleport the passengers?
is there are way i can auto detect "pre teleport" and when its finsihed, cuz i dont want to manually do taht every teleport
as those entities might themselves have passengers
no not really
just shove it in a util teleport function and call that instead
someone should make an API method for that
yes!!
well? get to it.
idk how to use github
:Clueless:
doesn't paper teleport with passengers by default now
ok thanks
same world is fine
right
?jd-s
i did something like
service.getSpawnLocation(player).thenAccept(location -> {
if (location == null) {
PlatformScheduler.of(plugin).runSync(() ->
R18nManager.getInstance().msg("spawn.spawn_not_found").prefix().send(player));
return;
}
PlatformScheduler.of(plugin).runSync(() -> {
ensureSafeLanding(location);
player.teleportAsync(location);
R18nManager.getInstance().msg("spawn.teleported").prefix().send(player);
});
}).exceptionally(ex -> {
PlatformScheduler.of(plugin).runSync(() ->
R18nManager.getInstance().msg("spawn.teleport_failed").prefix().send(player));
return null;
});
/**
* Creates a Bukkit world honoring per-world plot generation overrides.
* Pass {@code null} for any override to fall back to the global config.
*
* @param name the world folder name
* @param environment the world environment
* @param type the multiverse world type
* @param plotSizeOverride per-world plot size (PLOT only), or {@code null}
* @param roadWidthOverride per-world road width (PLOT only), or {@code null}
* @param schematicName per-world schematic name (PLOT only), or {@code null}
* @return the created Bukkit world, or {@code null} on failure
*/
public @Nullable World createBukkitWorld(@NotNull String name,
World.@NotNull Environment environment,
@NotNull MVWorldType type,
@Nullable Integer plotSizeOverride,
@Nullable Integer roadWidthOverride,
@Nullable String schematicName) {
try {
var creator = new WorldCreator(name)
.environment(environment);
var generator = getGeneratorForType(type, plotSizeOverride, roadWidthOverride, schematicName);
if (generator != null) {
creator.generator(generator);
}
var world = creator.createWorld();
if (world != null) {
world.setKeepSpawnInMemory(false);
logger.info("Created Bukkit world '{}' (env={}, type={}, plot-override={}/{}, schematic={})",
name, environment, type, plotSizeOverride, roadWidthOverride, schematicName);
}
return world;
} catch (Exception e) {
logger.error("Failed to create Bukkit world '{}'", name, e);
return null;
}
}
but i also set the spawnlocation always manually lol
my issue was that the player had a passenger, so it couldnt teleport, but still thank you!!
you can dismount it, store it somewhere then mount it back after tp
how can i get the new world on PlayerChangedWorldEvent ? Maybe player#getWorld ?
Yes
Is there any upgrade animation I can create? In older versions it's usually just sound and title, but I think the newer versions allow for a cooler animation, like adding an item to the screen. How can I do that?
Totem animation ?
You can change the item somehow, at worst just use item model data
yeah any item can bear the totem use animation if that's what you're talking about
or maybe you're talking about sprite object components?
need resourcepack?
yes totem animation
I'm unsure if you can use API to do it with any item
If not, item model component
But it shouldn't require resourcepack
how can i do with totem?
I have no idea lol
But it is 100% possible in some form :)
https://www.youtube.com/watch?v=RlgfggheNAE&t=17s i think t his need resourcepack
Yeah that needs a resourcepack
You can popup existing items but if you want text like that a resourcepack needs to add it
i just need existing items
how can i do that?
hey guys how do i
i recommend you skim over this whole page, because it basically answers 80% of "what/how can i do" questions pertaining to items, or at least gives you a starting point
/give @s nether_star[death_protection={}] this is not working
im just receiving the item
yeah, give gives you an item
and how can i play the anim
yes but they specifically asked about DataComponentTypes
It's some packet, no clue how to call it from API, if it exists
But there is some plugin that does this
are you talking about the totem of undying animation?
yes
wait a sec
can't you just do player.playEffect(EntityEffect.PROTECTED_FROM_DEATH)
that's the totem animation thingy
How does it determine which item
for custom model?
It'll use the default totem textures unless you got a totem with custom model data in your hand
If you wanna force a specific model data, you'll simply have to fake it, e.g.
fun totemAnimation(player: Player, modelData: Int, numStopSounds: Int) {
val item = player.inventory.itemInMainHand
val totem = ItemBuilder(Material.TOTEM_OF_UNDYING).setCustomModelData(modelData).build()
stopSound(player)
player.inventory.setItemInMainHand(totem)
player.playEffect(EntityEffect.PROTECTED_FROM_DEATH)
player.inventory.setItemInMainHand(item)
stopSound(player)
Nah you can give any item the death protection component now
yes I know
And I think it’ll play the animation with that item
but you won't have the animation
Ah
no it won't
Rip
only totems will show the animation, others will just "silently" revive you
(at least that's the case when forced through the EntityEffect)
pretty sure it plays the animation if it has the component
but yea if u wna just send the animation on its own, then u needa do it that way
@quaint basin here's your answer
but this need resourcepack right
myea the item model itself id assume is provided by the resource pack
No, you can use any model from vanilla
If you want custom textures/model then yes, it would require resource pack
Example from alex uses custom model data, you just need to use item model component instead
mcsrc.dev/1/26.1.2/net/minecraft/client/multiplayer/ClientPacketListener#L1210
bro forgot to check mcsrc.dev
membrillo
It was easier to just open the game lol
-# and yes my ign is Membrillo, it’s an investment
Man just got sponged
How do I appeal a ban on my Spigot MC account?
?support Email support
that's what I'm sayin
someone should make a totem system but it uses player heads
like lifesteal i guess? but not
idk ive never played a lifesteal server
I wanna make a Minecraft server I need a dev
?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/
why need stopSound(player) ?
oh i see
why i need 2 stop sounds call?
private void totemAnimation(Player player) {
ItemStack item = player.getInventory().getItemInMainHand();
ItemStack totem = ItemStack.of(Material.GRASS_BLOCK);
player.getInventory().setItemInMainHand(totem);
player.playEffect(EntityEffect.PROTECTED_FROM_DEATH);
player.stopSound(Sound.ITEM_TOTEM_USE);
player.getInventory().setItemInMainHand(item);
}
this is not working perfectly
just showing a totem on the anim instead grass
probably cuz the animation is hard coded with totem no ?
Nope
I do the same thing
@quaint basin the answer is to use a schedular
here's an example
no need scheduler
private void totemAnimation(Player player) {
ItemStack item = player.getInventory().getItemInMainHand();
ItemStack totem = ItemStack.of(Material.POISONOUS_POTATO);
totem.setData(DataComponentTypes.DEATH_PROTECTION, DeathProtection.deathProtection());
totem.setData(DataComponentTypes.ITEM_MODEL, new NamespacedKey("minecraft", "netherite_upgrade_smithing_template"));
player.getInventory().setItemInMainHand(totem);
player.playEffect(EntityEffect.PROTECTED_FROM_DEATH);
player.stopSound(Sound.ITEM_TOTEM_USE);
player.getInventory().setItemInMainHand(item);
}
this is working for me
just need this: totem.setData(DataComponentTypes.DEATH_PROTECTION, DeathProtection.deathProtection());
right i forgot, been a while
This is dangerous because you remove the item ticks afterwards
you're welcome
3200 players running this
lmao
Does anyone know why player#isOnline in GameProfileRequestEvent returns false when I log in with a premium user-bedrock? I'm using geyser-standalone and velocity.
?jd-s wtf is that event even
oh not a spigot one, got it
Is there a way to get the amount of invincibility frame a player has ?
im using 1.8.9 btw
Nodamageticks maybe?
im making a permission manager any ideas on how to model permissiongroups having a title or not (some groups like admin are displayed, while others only serve the permission purpose)? I dont really like the idea of nullable fields
hum where do you get that ?
oh ty I found it
player.getNoDamageTicks() btw
Yes this one
Its so weird the noDamageTicks says 20 but u can damage a player again at 10 ticks
like
tf
Hmm that's weird
Like it should be 10 ticks cuz its half a sec
But I dont get it
1.8 is pure madness
if I do event#setKeepLevel(true) on PlayerDeathEvent then the xp will be dropped?
it will be dropped setDroppedExp(int) use this to disable
setKeepLevel(true) is to player keep the xp right?
how do i regenerate classes csrg mapping
yes
I mean bukkit-1.16-combat-6-cl.csrg
What
i want to port bukkit to a snapshot and it seems like the last thing i need is a classes mapping file for that snapshot
https://spark.lucko.me/IEi6n9dXDO what caused the low tps?
Optional
Wait really
Hear me out, optional field that is null and we use a method to assign it
What could go wrong
Hey, I want to add protocollib v 1.3.5 (1.8) to my plugin, but the repo is not available on spigot, how can I add a custom repo for the dependency in the maven config file ?
the same way u added the spigot repo to ur maven pom

IntelliJ will yell at you about it
OHH right ty
just 1 question how do I know what the id is ?
Is asking for help on making bukkit mappings for a random snapshot forbidden here?
Anyway im not gonna care its not your responsibility to make a bukkit port for every version that ever existed
I will just rewrite all plugins for sponge
No it's just I doubt anyone can help
<repository>
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/repository/public/</url>
</repository>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>3.6.5</version>
<scope>provided</scope>
</dependency>
I'm trying to add protocol lib as a dependency but I get this error : Could not find artifact com.comphenix.protocol:ProtocolLib:pom:3.6.5 in spigotmc-repo (https://hub.spigotmc.org/nexus/content/repositories/snapshots/)
It's not even using the right repo no ?
wait
am I a chungus
I just dont understand how that works
ig because it's not serializable
it just kinda doesn't fit well with Java, since its just a null wrapper anyway
u dont get method overloading, and then u still have to evaluate at runtime if an optional is empty/present
but I think it can be plenty fine to use Optional more than just on return types if that's your style/convention preference for whatever reason
Ok so I cant add protocol lib as a dependency via maven cuz its in an old version, but how can I do it manually ?
https://spark.lucko.me/IEi6n9dXDO what caused the low tps?
have you taken an allocation profile yet
seems like your network took a dump
the issue derives from a native
its also possible that isn't the case as well since spark can't read the native calls properly
but the native in question is what java uses for sleep functions
but, it is also the native for input/output and networking
i think is a redis issue
https://mclo.gs/hi0Ga78 maybe this can help you
seems it is box-plugin possibly causing your issue
which seems to make sense too
it can't teleport, and you are using forge?
why not carbon chat?
carbon-chat only affects chat which doesn't affect TPS or shouldn't anyways unless you are trying to do things sync but I didn't see any of that in the profile
It indirectly affects TPS
that's the one he's writing iirc
5556 lines | 100 errors
i'd also take an allocation profile just in case it's zgc backpressure or something, but eyeballing the spark report it doesn't feel like it
This is a bug that I've already fixed, but it doesn't affect the TPS
if its already fixed then why are you showing old logs?
https://pastes.dev/ZDDTrPuGky world was passed as null here
because didn't this happen again?
this just happened 2 times
then its not fixed if its still throwing NPE's
The NPE error in the box-plugin has been fixed - not the thing that caused the TPS to be at 1
then why are you showing old logs that don't contain your fix?
u mean ./spark heapdump ?
because didn't it happen again?
it.unimi.dsi.fastutil.shorts.ShortArrays.forceCapacity()0.76%
libjvm.so.OptoRuntime::new_array_nozero_C()0.38% libjvm.so.ZCollectedHeap::array_allocate()0.38% libjvm.so.MemAllocator::allocate()0.38% libjvm.so.MemAllocator::mem_allocate()0.38% libjvm.so.MemAllocator::mem_allocate_inside_tlab_slow()0.38% libjvm.so.ZCollectedHeap::allocate_new_tlab()0.38% libjvm.so.ZObjectAllocator::alloc_object_in_shared_page()0.38% libjvm.so.ZHeap::alloc_page()0.38% libjvm.so.ZPageAllocator::alloc_page()0.38% libjvm.so.ZStatInc()0.38%
And that NPE error you're talking about isn't what caused the TPS to be at 1.
okay nevermind it does feel like zgc backpressure
have you taken an alloc profile yet
it is possible it could be allocation issue, libc also controls that too
is this heapdump?
no
it's the spark command i told you to run when you run into the issue
that profiles allocation rate
this? spark sampler start --alloc
more specifically i asked you to run a profile when the server is running normally, to get a baseline
and run a separate profile when the issue is occurring, to compare
yes
i didn't yes
but also pass --thread *
spark sampler start --alloc --thread *
yes
how many time should I run?
.
but how many time
enough to get an understanding of your baseline
like 5 minutes?
depends
take a report, look at it, try to get a grip on what's going on
if it isn't enough, take another
rinse and repeat until you have an understanding of your setup
that way when something like this happens and you take another report, you can tell what's going wrong and where
running a server, minecraft or not, without someone you can throw money at to disappear your problems is like working with an old car
Yes, sure, but I'm using free software, so maybe sometimes i can have free support
maybe i'll try contact carbon support to see why the plugin logged many times
no-one can understand your specific setup and stack for you
I doubt its the chat plugin
last time i saw something similar, it was with DhSupport
i.e. the serverside plugin for distant horizons, the level of detail type view distance extender mod
whoever wrote the plugin was a bumbling buffoon and was initializing some massive compression library anew for each individual block column when scanning the world for building the lod chunks
it was "async" but that doesn't help when you shit up the gc
that is crazy
well they could enable gc output with a jvm argument
to help see what the gc is doing or if its overworked and requires more resources
fosho
the zgc stats on the spark profile look normal-ish, so i'm not sure if it's gc pressure
either an alloc profile comparison vs a baseline or a gc log would be needed to go further without it just being guesswork
that said i've never even looked at a zgc log so i probably won't be of much help there
last time i debugged this with dhsupport it was just a matter of taking another routine alloc profile and seeing massive bleeding red million-gigabytes-per-second allocs under DhSupport ArrayCache right at the top
Supp supp
net.minecraft.server.network.ServerGamePacketListenerImpl.handleMovePlayer() 927.73ms
org.apache.logging.slf4j.Log4jLogger.warn() 927.7ms
lol
Seems fine
what this means
does adding an itemstack to an inventory lead to a copy of said item? does the item in that ui update if i change the itemmeta?
from what i remember, getting an itemstack from an inventory results in a craft mirror and modifications to the itemstack instance you get will be reflected in the inventory
but iirc, setting an itemstack into an inventory clones it, and changes made to the itemstack afterward won't be reflected in the inventory
generally i would advise doing defensive cloning and explicit inv.setItem regardless of how it behaves without those, as (as you can see) relying on the internal behavior is not easy to reason about
cloning itemstacks is very cheap nowadays as well
i.e. when getting from an inventory, always clone; when making changes you want reflected, always setItem (and optionally clone for clarity, though iirc you don't need to)
okay thank you, because im currently trying to update some lore on the items and either the updating is failing or the display of said updates.
so if i change lore setitem, even though it should update?
alright thanks
twofold, basically; you want to get rid of the "should"s so that the code is easy to reason about without knowing the nit and grit of bukkit internals;
- when you retrieve the item from the inventory, call
cloneon it, so you know for sure changes made on it won't ever be reflected in the inventory - after you make changes to the item, explicitly insert it back into the inventory with inv.setItem, so you know for sure the changes made will be reflected in the inventory
this way you aren't relying on nebulous presuppositions like "the itemstack i get from the inv should be a wrapper" or "the itemstack i set in the inventory should get cloned"
update some lore on the items and either the updating is failing or the display of said updates
also, make sure you call ItemStack::setItemMeta after modifying the meta and adding the lore
getItemMeta is always a clone and changes made to it won't be reflected on the stack until you call the setter with the modified meta
yes
okay
Is it possible to send a message to all players on a Bungeecord/velocity server on a backend plugin without a proxy plugin?
no
yes
there's some bungee messaging channel for it iirc
^
the bungee proxy defines some builtin channels and request-response style "endpoints" through them, like listing online network players, sending players to backends, and sending chat messages
i forget exactly what the channels are, you can look them up in some bungee documentation for sure
myeah
There is nothing to send a message to all players; only to one player
Message/MessageRaw accept "ALL" as targets
what if i want to send a message to a player named ALL specifically 🤡
this is not specified on this docs
but alr thanks
that's the bungee protocol for ya
i would be surprised if it did
given that players can't join yet while plugins are enabling
i did /plugman load
so have online players
💀
lol
why is this spamming
The server that sent the message has 7 players, and the number of messages was 7. This is probably related
well, you are using ALL as target, and you are sending the plugin message to every player in the server (Server#sendPluginMessage will broadcast the payload)
ohh server#sendpluginmessage is a broadcast
so the message will get sent to every player for as many players there are
so should i use player#sendPluginMessage
myes
can i do this with server#sendPluginMessage ?
i mean, not really
if your goal is to send the message to every player in the network, then you need to send one payload, to one player, and that will do the MessageRaw to ALL players
don't you already have redis messaging set up
i'd really advise against relying on the bungee messaging nonsense for anything in production if you can avoid it
i think it's a lost cause and just go and play ball with whatever he brings next
This is for editing a crates plugin
I don't like the fact that I have to have a plugin to listen the event on the proxy
Or else, if I don't use a proxy, I have to have a listener on all back-end servers
Since it's just a message to a player, I don't think plugin message is a problem
i mean, if you don't have a proxy then the pluginmessage approach will be useless
as the payload will be sent directly to the client, there is no mitm to intercept and process it
redis has nothing to do with the proxy
despair
I can listen for the event on the proxy or on all back-end servers - which I don't particularly like if I'm only sending a single message
what does this have to do with redis
How can I use Redis without doing it this way?
I'm thinking about using publish/addListener
currently, you are using the bungee proxy as a messaging broker; you send a message from one backend, have it delivered to all other backends, listen to it on each backend, and handle it appropriately
this is exactly, 1:1, what redis messaging does
except it doesn't need a player to be online and doesn't leak random plugin messages to the client
pub-sub, yes
But the problem with that is that I need to have the plugin on all servers
that's no different from what you're doing now
you already use redis
also no, not really
e.g. rabbitmq runs with like under 10mb memory
whats the issue?
I need help. Everything is basically correct, but it can't find plot.manager.Plot. Can anyone help?
?
Good evening, fellow plugin developer.
what plot.manager.Plot are we talking about? did you add the dependencies?
or is it ur own code
here sorry its german
Or is GPT code referencing something that doesn't exist?
but the fact that the message has to be queued to be sent to the main thread etc
is ur Plot or PlotManager maybe a private class?
I don't know, but either way I think it's simpler this way. It's just easier to set up the plugin
own
idk wait
no public class
ur package is wrong
the package at the top is wrong
huh
yeah, you're in a wrong package
tf did i wrong
you might wanna move the whole plot thing under the other package
I don't get it right now.
did you copy that class around?
the package at the top of the file is wrong, it is not the same package the file is in
Can I send all of this in here?
they need to match
Yeah Intellij is also telling you what's wrong
just drag you plot folder into the me.bropro... directory
that seems like the place it used to be
and you figure the bolted-on afterthought that is the bungee messaging api does it better and more efficiently than the dedicated-from-scratch messaging broker that's been around for about as long as minecraft?
me.Plot.plot.manager?
??
Now it says that the package plot.manager is not present.
i updated it 2 days ago 😔
can i return to the old one
i updated intellij and they forced me
there's a plugin that restores the old ui, but i'm not sure if it works on the 2026 builds
its not plot.manager, your package starts with me.bropro....plot...
nice
eyeballing the metadata, it might work still
fair enough; but I'm just doing that just for simplicity
to do the setup easier
it's a fair point that using bungee messaging means less setup
i dont really know what the whole discussion is about, but i can tell you that redis harder at first but its gonna help you out a lot if ur building a network
at some point you need redis either way
Regarding Redis messaging, would you advise publishing to all backends and listening for the message on the proxy, or publishing/listening to all backends?
Could someone please fix this for me? I can't cope with it anymore.
you're begging to get clown emoted
publish where the data comes from and listen where the data is needed
bropro I'd recommend learning java first
it seems like ur having trouble with some basic issues
?learnjava
For Beginners:
Codecademy - Learn Java: Interactive Java programming course from basics to more advanced concepts. Perfect for absolute beginners.
https://www.codecademy.com/learn/learn-java
JetBrains Academy - Java Developer Track: Learn by doing with projects and challenges. It covers Java fundamentals to advanced topics.
https://www.jetbrains.com/academy/
Udemy - Java Programming Masterclass for Software Developers: Updated courses that cover Java 8 to Java 17 features. Suitable for those who prefer structured learning.
https://www.udemy.com/course/java-the-complete-java-developer-course/
For Intermediate to Advanced Learners:
Oracle Java Tutorials: The official guides by Oracle for Java programming—great for understanding the depth of Java.
https://docs.oracle.com/javase/tutorial/
Baeldung - Learn Java and Spring: Focus on Spring Framework and modern Java technologies. Best for intermediate learners aiming to expand their knowledge.
https://www.baeldung.com/
Practice and Hands-on Learning:
Exercism - Java Track: Solve exercises and get feedback from mentors. Great for practicing coding skills.
https://exercism.io/tracks/java
LeetCode: Practice your coding skills and prepare for technical interviews with Java.
https://leetcode.com/
Free Resources and Documentation:
Java Programming and Documentation: A comprehensive collection of Java programming guides, tutorials, and API documentation.
https://docs.oracle.com/en/java/
Community and Support:
Stack Overflow: A vast community of developers. Great for getting help with specific problems or understanding concepts.
https://stackoverflow.com/questions/tagged/java
r/learnjava on Reddit: Join the community of Java learners and get advice, share resources, and discuss projects.
https://www.reddit.com/r/learnjava/
Remember: Learning to program takes practice and patience. Don't hesitate to experiment with code and participate in community discussions. Happy coding! 🎉
Nevertheless, could someone please help me?
i alr told you the fix to your issue
I haven't been doing it for very long either.
are you ai generating ur responses?
yes im german
But let's say I want to send a message to the players on server A, server B, and server C that are behind proxy D.
There are two approaches to do this:
For example, I execute publish on server A, and then the proxy listens and goes through all the players on the proxy and sends the message (without listening to anything on servers A, B, and C).
Or:
I execute publish on server A, and then servers A, B, and C listen to the message and go through the players on each server and send the message
both will be the same thing?
bropro trust me if package management is causing this much trouble, your not getting far with whatever your developing, i would really recommend to learn some programming basics
but can you help me with this
i recommend sending messages to players on backends rather than on the proxy
no i alr told you what ur supposed to do, pls learn java
because:
- backends have more context to e.g. parse papi placeholders
- backends might have other plugins controlling or recording chat
And you don't want to help me?
also, reloading plugins on backends is simpler than on the proxy
I didn't understand the second point
I already helped you, but it seems like you couldnt understand what im saying
therefore its better to learn java
u mean restart the backends is simpler than on the proxy?
bc suppostly we should not use plugman xd
You could help me out for a bit, but it's okay, I'll manage somehow. Thanks anyway.
using plugman is fine as long as you know your stack and know what you're reloading
personally, i write all my plugins to support reloads
to the extent where i don't even implement config reload commands; i just expect an admin to reload the whole plugin
reloads u mean plugman reload?
yes
But that really slows down the server, doesn't it? For example, when saving to the database after the plugin is turned off
a second-or-two lagspike when reloading a plugin is acceptable, especially if it's announced ahead of time; for certain more acceptable than minutes of downtime from a full restart
should i always locally cache global data, if i read it once, the 1ms from redis doesnt sound a like much, but its gonna build up isnt it?
cache global data, or use futures?
do not redis connections on the main thread
i mean we're talking about using it for messaging, not as a key value store
but yes, just 1ms for a key value access on the main thread is unacceptable
cache coherence is its own beast
its not about the discussuion, i was thinking for my project 😅
And if Redis goes down for some reason, W server
in principle futures are the most robust solution, but they force your business code to always be threading-aware which can complicate things
Future sounds good, i mean if the data isnt there yet im i can just type loading... into my ui cant I?
my preferred approach was to put together a cache coherence system that maintains exclusive ownership of key-value pairs based on which server a player is online on
so if you have an online player, you're guaranteed to get up to date data from local memory
I would just go about it in a way that your global data isn't anything you need to be constantly querying
player.getInventory().clear(); does this include the armor contents and the cursor etc?
for offline players, i still use futures
just design things better™
true, but i was thinking a /ban command and for that i most definitely need that
i'd handle that on the proxy
But can't the data be updated by other servers?
easiest way to deal with distributed data is to not have distributed data
so you cache the data on the server that player is on and other servers read with futures?
implement /ban and the ban checks on connect in a proxy plugin
i think /ban just need a database no?
backends don't need to know about it at all
i get that, but i like my backend code tbh
yes but i want to do it a ✨ special way
myes
what the advantages from using redis here?
it gets a bit hairy because according to the velocity proxy spec, a player can be online on two backends at the same time
there are none, just that i like working with my backend classes and i dont like proxy code
I mean, if you just want to be unproductive, there's better ways to do so
my proxy is just bare bones
:(
player.getInventory().clear(); does this include the armor contents and the cursor etc?
i absolutely fucking hate writing proxy plugins as well
yes!!!!
velocity is the #1 proof that paper should never have been given full control of the ecosystem in any project
im not sure what you mean by that
that said sometimes doing shit on the proxy is just worth the headache because it avoids several headaches elsewhere
yeah i dont like my proxy, it basically just routes my players, and kicks them from the proxy once it receives a redis message to do so
muh fucking toml
why
because yaml is too mainstream
no we MUST use the hippie bullshit config format that nobody knows about
but regarding the previous topic, do you think i should also try caching globaldata on other servers and invalidate it after change?
it depends on what it is
u are talking about the sponge thing?
that is needed on velocity
caching + invalidation still means there's a window where you can read stale data
for some purposes, this isn't acceptable
its just cosmetic data
so tbh
it doesnt matter
suppose for example a player's balance; all operations on it must be atomic
my free economy plugin with multi server support is 🔥
if it's mostly read-only and brief windows of stale data are acceptable, caching + invalidation via e.g. redis is fine
i could also try redis livedataobjects, pretty sure they are atomic
the thing about being atomic is that you can't really have your cake and eat it too
if it truly is atomic, it can't be truly cached
yeah right
because another server could make a change to it and it won't be reflected on your end instantly
sounds like futures are the way, most of the data i read globally isnt even really important to have fast access
notwithstanding strategies like compare and exchange
My economy plugin performs real-time operations on db but uses caching for scoreboard and /money view reads, which tolerates inconsistencies
that's great until someone does /baltop on the main thread or something
my /baltop does not use cache
purely database
uhh
my point is that this approach only works as long as you control all read call sites
real time + infinite pagination
if you have any plugin accessing it via e.g. the vault api on the main thread, you have only two choices: return potentially stale data, or block the main thread
im not using vault to my economy plugin
the first can be disastrous if it's used for something more destructive like a transaction
the second can be disastrous if it's done in bulk
I have no idea how to use Vault to create economy plugins with multi-server support
you can't basically
What amazes me is that plugins like Coins Engine have so many users xd
well you can, but
I'm querying the database for each page; perhaps this is a problem for high-end players because although the query cost is low because I use strategies like indexes + seek pagination, it's still a database query. Maybe this isn't scalable
database queries are the very definition of scalable
but they do have a base latency, so you don't want to do them on the main thread
a database query for baltop off the main thread is probably the best approach in principle
you could add a cache in between to avoid doing duplicate calls, but it isn't strictly necessary
Yes, of course, my concern is CPU usage If 50,000 players decide to execute /money top, that's 50,000 database queries, which the database probably won't handle very well. But also, I think it's unlikely to have 50,000 players on a single machine. So yeah
the database will handle it much better than your minecraft server will, for sure
cache where?
yea
i'd probably just cache each baltop page for a minute or two
that way when players paginate back and forth you can reuse the already-fetched pages instead of doing new queries on each pagination
I don't do this to update in real time
And since with seek it's log(n) where n = number of registered users, then it's fine
50k queries are nothing for a modern database
and you won't ever have 50k players so you don't have to worry about that
at least not in a single network lol
I've already managed to get 250 in 2 server months 🔥 I just need 47,500 more
the limit for a new server is around the 10k
donut is not have like 1 year?
yeah but donut had massive reach due to the amount of youtubers playing in it
i think drdonut was already a famous streamer ye
oh alright thanks
?jd-s
anyone knows how i can serializers to my redisson client?
how you can what serializers
*add
i found that i can change the codec, altough i cant add serializers to the kryo5codec
i dont really want to write a full codec
just so i can add serializers
Can you do something like
import org.redisson.codec.Kryo5Codec;
public class MyKryo5Codec extends Kryo5Codec {
public MyKryo5Codec() {
super();
}
@Override
protected Kryo createKryo(ClassLoader classLoader, boolean useReferences)
throws ClassNotFoundException {
Kryo kryo = super.createKryo(classLoader, useReferences);
kryo.register(MyClass.class, new MyClassSerializer());
// orrrrr
kryo.addDefaultSerializer(MyClass.class, new MyClassSerializer());
return kryo;
}
}```
Excuse my formatting
okay im gonna try that, thank you :)
yea that's how we do it at work
work you mean on enterprise?
is there an advantage to using nms vs normal bukkit for creating and moving entities in terms of performance
nms is just internals
bukkit uses internals to implement its API, just how the server works
there are some instances where Bukkit/Spigot's wrapping might induce some performance penalty, but spawning of entities isn't one of them
ok thanks
if you use bukkit api the plugin will require less upkeep
an upkeep that ranges from renaming the import to reading javadoc for a few minutes to figure out replacement
The general consensus is you minimise nms usage to take advantage of the magic of bukkit api that lets plugins from 1.8 work on 1.21
there is some changes in the api though that even plugins relying only on that will still break from 1.8 to 1.21
Because 1.8 to 1.21 is almost a new game
I mean this is a given.
freetolga isnt saying that using the API is failproof
but rather, that it is far less maintenance hungry than nms
Which tools were used to update bukkit mappings in the past
Whenever i tried using specialsource to compare 2 jars i ended up with a stack overflow
I think I just hit some kind of compiler freak error
.NoSuchMethodError: 'net.minecraft.world.level.storage.LevelData net.minecraft.server.MinecraftServer.getWorldData()'
LevelData is a whole different interface idk how it compiled to target that
this is like discovering a new star homeboy
You get to name this error now
Illusion’s Illusion might work
you're doing some kind of remapping wrong or compiling & running on wrong mappings
n.m.w.l.s.WorldData is the spigot name for n.m.w.l.s.LevelData
but mojang names also have a n.m.w.l.s.WorldData which on spigot it's named n.m.w.l.s.SaveData
https://mappings.dev/1.21.11/net/minecraft/world/level/storage/LevelData.html
https://mappings.dev/1.21.11/net/minecraft/world/level/storage/WorldData.html
ggwp
just don't reobf
Decomp output is not remapped
Only the interface call
I think papers remapping thing is getting in the way
Idk if paper-nms puts its mappings thing in the manifest
Hello someone can help me with Items in plugin multiversion?
I need to get Items from Inventory of InventoryCloseEvent, but in plugin multiversion, in my common module (spigot api version 1.8) the InventoryCloseEvent is triggered and filtered, so far, so good, but when I filter items with if (item == null || item.getType() == Material.AIR) items from 1.20 not are not detected as an item, they are detected as air, Can anyone help me with this dilemma?
I've already tried it, and it didn't work:
- Send Inventory contents to my class of adapter and process it there
- Send InventoryCloseEvent to my class of adapter and process it there
Thanks in advance
Mojang no longer obfuscates NMS correct
true. next question, what about craftbukkit, its still being relocated right?
Probably

now I tried this, but that means my plugin won't work in version 1.8
not true
will still work in 1.8
That field didn't exist in earlier versions so they don't care
well
some stuff will break on newer versions and not older ones
like renamed material or whatever
hmmm ok, thanks for the help
Nope
No relocation
Yep
I just use bukkit.getversion and get the feature that way
Currently it works for 26+
Hopefully it won't need maintenance for the time being 😄
https://pastes.dev/E7Vbo5fMEi Am I forgetting something? I want to clear my inventory completely
whats happening
what parts of the inventory arent clearing
?jd-s
if you are in creative, setCursor does nothing
im on survival
i want clear everything
i think im clearing everything
not sure
but so... what isnt clearing?
i mean, Inventory#clear will already take care of the armour slots and stuff
you don't need like 80% of that code
what can i remove
im asking if i need add smth or if i can remove smth
you just need the Player setCursor() and Inventory clear()
