#help-development
1 messages · Page 1324 of 1
A easy to use Paste site for Minecraft Server logs.
DuelKits 50 is DuelKit defaultKit = new DuelKit("Default", Material.IRON_SWORD);
Could you share your DuelKit class
A easy to use Paste site for Minecraft Server logs.
Hmm
Could you DM me a copy of the jar
And grab it from the server
Not project folder
Too old! (Click the link to get the exact time)
Hi guys! I'm having an issue cancelling the block action packet for a double chest. I have a print going to console to let me know that the code passed all the conditions, and it works perfectly for a single chest, but not a double. Here's the code: https://pastes.dev/0CDg8Wy7Y1
I was told to cancel the packet for both sides of the chest but I don't know exactly how to do that. Help please!
Just add the location of the other side of the double chest to your vanishManager
You can check the block state if it's a double chest or not
I'm sorry, I still don't get it
(I havent read the code I'm just basing my answer off what Olivo said - assuming what the issue is)
A double chest is really two chests. You're only interfacing with the one chest; you can determine if a chest is double based on its blockstate, from this you can determine the position of the adjacent chest, to also interface with this.
Yep I know that, but don't get how
for a double chest to work, it must be placed facing the same direction as the other chest, with this knowledge in mind, you can say for certainty a chest cannot be behind, above, below, or in front of another chest to be a double chest, your directions are left and right.
it usually tells you the direction of the second chest in relation to the one being accessed
I think you can do:
InventoryHolder holder = block.getState().getInventory().getHolder();
and cast holder to a Double Chest?
Well what about double chest.getLeft() and getRight()?
you can always do the old fashion route too
but also, is there a particular reason you need to do this with packets?
yeah thats what i meant, those are properties of DoubleChest, so cast InventoryHolder to DoubleChest
yes I tried that
getLeft and getRight should return a holder, which you can get coords from
Yep
don't have the docs up so can't say for certain
Chest chest = (Chest) block.getState();
InventoryHolder holder = chest.getInventory().getHolder();
if (holder instanceof DoubleChest) {
DoubleChest doubleChest = (DoubleChest) holder;
Chest leftSide = (Chest) doubleChest.getLeftSide();
Chest rightSide = (Chest) doubleChest.getRightSide();
Location leftPos = leftSide.getLocation();
Location rightPos = rightSide.getLocation();
...
Is this not right?
yeah I did that
It didn't work
And what does that mean? Can you try logging it
you should verify your code is in fact correct by having it spit out the coords of those objects
its very easy to use the incorrect holder
visually? does the GUI open?
oh, you want the animation to not happen
thats probably client side bs tho
both
Yeah I want to cancel the animation
I don't know why it works for every other container
Im confused, you want the GUI to open but not the animation?
If you want neither to happen, then just cancel the event, the animation will never play?
I want the GUI to open
Okay, so is the opening animation happening for both the chests, or just one of them?
both sides
Can you show your full implementation of how you're doing it?
With the double chest logic
Deleted :/
can you give the full context atleast, the parent class?
I'm not sure what you want to see. Vanish manager?
Yeah
Ok
I have no idea what ur code is doing
Ok one sec
if (vanishManager.containsLocation(location)) {
have u checked if it actually contains the location?
maybe log ; "left chest <pos> <boolean; is it in the vanishManager>. right chest <pos> <bool>"
Yep did all that
cancel the event, then use the API to have the player open the GUI
this should cause the chest to not open but the gui to still open
keep in mind if the GUI needs to be tied to the chest in question you will have to handle that yourself when the player closes the inventory etc
Does that mean tracking changes?
That's vanish manager, you can see I store the player and location so I can check if that player is in vanish mode
well yes, because technically the GUI inventory doesn't exist or isn't tied to a specific block.
in order to do what you are wanting
so instead of using the chests inventory to house the GUI, you have a generic inventory held in memory instead
what happens when multiple people are making changes at the same time?
depends how you coded it. There can be separate views of the same inventory(means everyone can see the same thing and see changes) or seperate views with seperate inventories(everyone sees the same inventory, but the inventories are all different instances so changes done are unique to that player)
but yeah, shouldn't be hard to do what you are wanting. Just when it comes to your event handler, instead of putting cancel event at the end of the method
you would do it near the beginning of the method, then add some code after to open your GUI
I noticed something interesting. It works after the chest was already clicked and closed once
check the order of ur code then
I don't think that's it because it only behaves that way for a double chest. I've got an idea though
I'm not exactly sure what I did but it works now
so true
I changed pairing a location and uuid to a list of pairs
Why player.setHealth plays damage animation? how can i stop that?
I'm getting an error trying to add the player back to tab list after they've been removed
Cannot cast java.util.ArrayList to java.util.EnumSet
In line 200
https://pastes.dev/4Xc8kuOojb
Wow
infoPacket.getPlayerInfoActions().write(
0,
EnumSet.of(
EnumWrappers.PlayerInfoAction.ADD_PLAYER,
EnumWrappers.PlayerInfoAction.UPDATE_LISTED,
EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME,
EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE
)
);
instead of infoPacket.getPlayerInfoActions().write(
0,
Set.of(
EnumWrappers.PlayerInfoAction.ADD_PLAYER,
EnumWrappers.PlayerInfoAction.UPDATE_LISTED,
EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME,
EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE
)
);
i have 4 classes that are records of 2 elements, 2 of them use ints, should i replace them with a single pair class?
and have the ints boxed?
is it worth it
yeah just give them proper names
better than having to deal with unnamed tuples Tuple getFirst getSecond like girl give me something
alright
use fastutil Int2IntMap.Entry 🤡
i need Object2Int but noted the joke
fastutil has all of them tuples
i know
but it's not part of spigot api
so i rather not use it
also it's part of map
not supposed to use it elsewhere
it has no reference to a map; it's also on the server classpath anyway
Hmm, that produces the same error
Line 200 is causing it, which is above that
Nevermind I fixed it 🙂
How do I send a TRACKED_WAYPOINT packet with ProtocolLib? I can't find any documentation anywhere and I don't know what to make of this
I tried to do this ```java
PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.TRACKED_WAYPOINT);
packet.getIntegers().write(0, 0);
packet.getUUIDs().write(0, new UUID(0L, 0L));
packet.getMinecraftKeys().write(0, new MinecraftKey("minecraft", "player"));
packet.getBooleans().write(0, true);
packet.getBytes().write(0, (byte) 255);
packet.getBytes().write(1, (byte) 0);
packet.getBytes().write(2, (byte) 0);
packet.getIntegers().write(1, 1);
Location loc = player.getLocation().clone().add(0, 0, 5);
packet.getBlockPositionModifier().write(0,
new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
Look at the NMS class rather than the protocol doc
Which class would that be for this? My first instinct is ClientboundTrackedWaypointPacket but I'm not sure what information to gather from that, not to mention it's not even under net.minecraft.server.
@echo basalt I've looked around and haven't really found anything helpful
the fields of that class are what you pass onto protocollib
protocollib doesn't interface with the wire byte-by-byte network protocol itself, which is what mcwiki documents
it's essentially just a reflection wrapper over the packet classes
the two can differ significantly
It's a record that stores an Operation and a TrackedWaypoint
not exactly sure how I would send those with the methods available lol
if protocollib doesn't have a wrapper type for it, you're kind of fucked
consider using packetevents or nms or reflection
reflection is relatively alright nowadays without the obfuscation messing it up every version
in this case you have these nice static factory methods already that you just pass an uuid + icon + coordinates to, that you can then send with protocollib
I can send those packets with protocollib?
I tested sending them with nms and it worked
I thought I needed to make the packet with protocollib to send it with protocollib
you create the packet container with protocollib, then call setHandle with your nms packet
and send it via protocollib as usual
it cuts a couple of reflective/nms steps
Nice
and conversely you can do nms stuff on packets intercepted by protocollib by getting and casting getHandle
no need to manually inject into the netty pipeline
Wait where do I call setHandle? Looks like its only available for the wrappers, not the PacketContainer itself
seems to be on the packetcontainer itself
oh you said sethandle
maybe i misremember; check the constructors maybe
myes
takes packet type and Object handle
no one cares
How can edit my plugin which I have published
thanks actually
ChatGpt moment
right bottom
edit resource
bet you can't make any plugin
bet
go
for what
i have modrinth and spigot accounts where i have my plugins
that i wrote myself
after it gets approved then will i get edit option?
it approved automatically i think
you can edit it rn
write like never use once
never
primitive
chatgpt cant write plugins
who said chatgpt write for plugins
?
mind yours
Don't spam your shitty advert. Doesn't belong here. Go to
Stop spamming, it will only get you banned
?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/
god why is message markdown like a default enabled permission
now let's hope mojang doesn't refactor every other version
oh there IS no permission to limit formatting
thats Bum
there is
nyo
On an avg hoe many days spigot staff take to respond to ticket?
Whenever staff have time
how would I go about detecting if a player is inside a structure? (paper 1.21.11)
?whereami
Oh it's been a week, shd I create a new one or it's bec of Christmas week
Depends on what you asked for tbh
Edit your message to say spigot
🤣
Guys do you think virtual threads are as good or better than a selector when handling multiple clients on a server?
1 virtual thread per client? Or a selector?
i like selector
but i'm not sure how they work exactly yet to confirm
i use classic sockets
and virtual threads myself
Ah okay
So selectors are definetely superior in terms of speed?
i haven't used them to confirm that
but i like that they're non blocking
so you don't need threads/virtual threads
i considered them at one point, but i didn't had the time to implement a test to see if i like working with them
they work a bit different than classic sockets
Okay
using selectors on VTs is like chasing a bus with a car, it doesn't make sense
as far as networking goes, VTs turn blocking operations on sockets to non-blocking under the hood to use selectors, you just write synchronous code and forget about it, it's simpler code, simpler to read, write, and reason about, 1 VT per socket is ideal as the whole idea is that they are disposable like that, you don't wanna be caching them or have a pool or anything
oh actually
i tried running virtual threads on a infinite loop once and it just stops
pretty sure it'll do the same for selectors no?
what
uh yeah that much doesn't really tell me anything, like how you're creating them or handling them outside; they are forcibly daemon threads tho so that's something to keep in mind
nothing changed tho
i used virtual thread instead of thread that's all
if no connection could be found it'd loop this for a bit then stops
yeah idk that's not how i'd write such code to begin with so i can't really comment without seeing the whole picture
i dont really understand what ur saying, i meant either using vts or a selector
Is there something specific I'm meant to set up to get this working? Trying to make a fork of a plugin and this isn't working right
missing dependency
you need to run buildtools on remap setting
i fixed it, i added a thread sleep of 1 second in the loop and now it works as expected 😄
i can use virtual threads everywhere yay
but yeah virtual threads just die in loops
it needs to be blocking
i have no idea how you're achieving that lmao
im running into some weird build issues if anyone knows how to help
I have a plugin I commissioned a few years ago here - https://github.com/BenButler77/Music
im trying to build it again with maven using 'mvn clean package' and it seemingly works, gives a build success and loads fine on my server
but line 126 in jinglenote/JingleSequencer.java is throwing an InterruptedException error despite there being error handling there
I'm 100% positive the code isnt bugged because I still have a copy of the jar that works fine so presumably something about the way im building it is screwy but I really have no idea where to even look
hoe many days 😭
any way to patch pie ray/abusing pie chart? any1 know of any plugins for 1.21.11, i've looked and cant find any
intercept ClientboundBlockEntityDataPacket
i've no idea either, but since the only difference in the code was if i was using threads or virtual threads i assume it's just a virtual thread thing
and to be honest it's better that i parked the thread for 1 second
the loop was too hot anyway for virtual threads
I think the block entity would still exist just with its default state data, so that wouldn't matter
But regardless, you can't really "fix" that. It's a debug chart. You're sorta shit outta luck unless you get something like Orebfuscator (or some other anti-xray plugin/implementation) to hide spawners, chests, etc. through walls
I got impacted by the GameRule changes. But the gamerule for DoDaylightCycle is just gone or? Any alternatives to be used now?
It's gone. It was replaced. ADVANCE_TIME is the new name
Okay that helps, thanks 🙂
hey
anyone know how to do the particle effect of trial chambers?
the particle name is ominous_spawning
its like many particles travel slowly towards a center and disappear there
it exists in the trials chambers but i don't know if there is a way to summon it or use it in a way
you can’t directly spawn ominous_spawning via commands or Spigot’s Particle API. It’s an internal, server-side particle hard-coded for Trial Chambers logic. There is no public enum, no namespaced particle
if im correct
what I have found when researching
public static void spawnOminousParticles(World world, Location center) {
Random random = new Random();
for (int i = 0; i < 20; i++) {
double radius = 1.5;
double angle = random.nextDouble() * Math.PI * 2;
Location spawn = center.clone().add(
Math.cos(angle) * radius,
random.nextDouble() * 1.5,
Math.sin(angle) * radius
);
Vector velocity = center.toVector()
.subtract(spawn.toVector())
.normalize()
.multiply(0.03);
world.spawnParticle(
Particle.DUST_COLOR_TRANSITION,
spawn,
0,
velocity.getX(),
velocity.getY(),
velocity.getZ(),
new Particle.DustTransition(
Color.fromRGB(30, 30, 30),
Color.fromRGB(0, 0, 0),
1.2f
)
);
}
}
``` (not my code)
or particle dust_color_transition 0.1 0.1 0.1 1 0 0 0 1 ~ ~ ~ 0.6 0.6 0.6 0 80 force
okay thanks ill try it
yes you can /particle minecraft:ominous_spawning ~ ~ ~ 0 0 0 1 100 works just fine
and the field in the "enum" is public
particle being "server-side" makes 0 sense
oh the Particle class is still an enum
world.spawnParticle(Particle.OMINOUS_SPAWNING, ....) will do
thanks you it works perfectly
ok steve
as I said, just something I found on google.
but thank you for clarification
Hello, can anyone help me with coreshaders?
I found a coreshader for text effects. The effect applies based on text opacity (alpha).
I don't understand how to make it work because we cannot use opacity on text in Minecraft (hex codes are usually only 6 chars). However, on the server where I got the shader, they succeeded to make it work.
So i would like to know how can I send a text with a specific alpha/opacity to trigger the shader?
i've tried, hoping doesn't help, they refactor everything anyway
ShaderLabs discord server can help you most likely
anyone know why the method sign.update(); doesn't seem to work consistently? when I call that function, it seems to work like half the time, and the other half it just doesnt update the sign at all. has anyone else had problems with this issue/know how to fix it? (trying to change the text of a sign)
Hey anyone tell me what the hell is going on with chat signing? I last modded minecraft in 1.12 era. Not sure what is going on and it also seems a little controversial? Like I'm completely out of the loop, just wondering if anyone had good context about that.
what about it
Like why does it exist, should I have it on / off? Does it have anything to do with this new "player reporting" feature?
Some people are calling it a microsoft thing too idk why
Because it is, and yeah it’s related to chat reporting
It works fine for me
?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.
hi, somebody can help me ?
| Aspect | Annotation | API | Difference |
|---|---|---|---|
| Initialization | O(n) scanning | O(1) registration | API is faster |
| Memory | O(m + c + s) | O(m + s) | API slightly lighter |
| Processing | O(1) + reflection | O(1) + reflection | Identical |
| Flexibility | Limited | High | API more flexible |
| Maintenance | Automatic | Manual | Annotation is simpler |
i'm making an API for using NATS in the minecraft ecosystem
NATS is a push sub messager
i have done a Java annotation and an another method to subscribe to a NATS subject (like a channel)
@NatsSubscribe("subject")
public void onSubject(String or byte[] data) {
System.out.println(data);
}
VelocityNatsPlugin.getNatsAPI().subscribeSubject(this,
ServerDiscoveryService.class.getDeclaredMethod(
"handleServerEvent",
byte[].class
), pattern, false);
pattern is the subject name
the method is lighter and more configurable than the annotation but not too simple to use
Annotation is mooore simple but cost more in terms of cpu time
what should i do
the problem with the annotation is that i need to scan the whole classpath of plugins loaded
and in @NatsSubscribe("subject"), "subject" needs to be a const, so it isn't configurable
his question is not a programming error but a simple question type "I use this function but it work half of time. Any alternative ?"
there have no more "code" to provide here
Yes??
sign.update() has some context at play? Like when you’re invoking it. Perhaps the issue lies in the context of where it’s used.
I understand now
No it's obviously the if (random.nextBoolean()) // fail I snuck in
I have seen a code for edit sign lines and "update" the signs
and other event for remove mojang reporting
In red "editString" is just for apply censor words, it not requierd
pssht don't forget to lowercase your method names right here
OnAnvilEdit -> onAnvilEdit
lowerCamelCase is the target
ok
Hey guys, does anyone know why the PlayerDeathEvent doesn't track the exact location where the player died?
I'm creating a /back (return to the location where it died) plugin, and for some reason it's not picking up the exact location where it died.
pls anyone help me build a mc seve pls i need pls
What is it picking up
It's retrieving the /spawnpoint location.
What method are you using?
pls anyone help me build a mc seve pls i need pls
pls anyone help me build a mc seve pls i need pls
pls anyone help me build a mc seve pls i need pls
pls anyone help me build a mc seve pls i need plspls anyone help me build a mc seve pls i need pls
pls anyone help me build a mc seve pls i need pls
pls anyone help me build a mc seve pls i need pls
pls anyone help me build a mc seve pls i need pls
pls anyone help me build a mc seve pls i need pls
d
pls anyone help me build a mc seve pls i need pls
I'm using the Player#getLocation method.
@EventHandler
public void onDeath(PlayerDeathEvent event){
Player player = event.getEntity();
Location location = player.getLocation();
locations.put(player.getName(), location);
}
Just a reminder: I'm testing on version 1.8.8.
Spamming the chat is not the way to get someone to help you 💀
It does the exact opposite
Do make sure you're at least testing on Spigot
and not a fork of a fork of a fork of a fork...
Yes, I'm testing it on Spigot.
1.8.8 is diabolic
a what?
I think the answer has to be yes but am I the only one for whom the teleport method is randomly just not working all of the sudden
it always gets cancelled
every single time
I can't see why
Try storing a .clone() of the location, idk about 1.8 shenenigangs
I already tried that, but it still didn't work. It keeps teleporting to the spawn point location.
when are you teleporting? try delay teleportation by one tick
I teleport using the /back command.
print out the location you have stored in your back command. is that location correct?
do you have "instant respawn" enabled or sth? print out the death location in the playerdeathevent. is that giving the correct death loc?
I'm using an auto-respawn method, and no, it's not printing the correct death location.
listen to PlayerDeathEvent on LOWEST priority
does that give you the correct location?
No, it's still showing the spawn point location.
then I also have no clue. Disable your auto-respawn stuff and it should work I guess
Yes, the problem is with the auto respawn itself. Isn't there any way to fix this with auto respawn?
show your auto respawn code pls
@EventHandler
public void onDeath(PlayerDeathEvent event){
((CraftPlayer)event.getEntity()).getHandle().playerConnection.a(new PacketPlayInClientCommand(PacketPlayInClientCommand.EnumClientCommand.PERFORM_RESPAWN));
}```
what if you print out the location above the getHandle() line? still wrong location?
Yes, when I print the location beforehand, it shows the correct location.
Doesn't the death event have a location getter? It is generally I'll advised to call getters on the player itself if the event could result in those properties being changed
I'd also advise delaying the respawn command to the next tick, or the end of the current tick, as doing that inside an event handler could have unexpected results with things happening out of order
then record a clone of the location there
then it should work
No, there isn't a specific method to get the death location. I'm retrieving it using the Player#getLocation method.
yeah but they're on 1.8 and doing weird NMS stuff
Do I need to use priority?
The respawn command is modifying the player; the location is already defensively cloned in the getter
Doesnt matter in your case
It's only working because of the priority setting.
wouldn't respawning in MONITOR priority fix getting the location in other priorities?
Yes, I've already managed to solve it; I'm using the LOWEST priority setting.
Thank you to everyone who helped!
Especially to @tender shard
you're welcome
not sure if its something to do with my code or how falling blocks work, but im trying to move a set of falling blocks smoothly but it looks really bad, they will all teleport, stop for a second, then teleport, it looks really janky
IIRC falling blocks are always janky - if I'd be you, I'd use Display entities instead, there you can perfectly control the "smoothness" using er... what is it called again
Interpolation Delay / Duration or sth
alr thanks
If you use velocity instead of teleport they also won't be janky
Unless something changed it does work, yes. The despawning issues do stay
I changed it to this (with display entities) but its still a bit janky like its very obviously teleporting but idk if it can get any smoother
Make sure to set the teleport duration (iirc) on the display entities
It’s how many ticks to interpolate when it teleports, but it defaults to 0 (no interpolation)
worked, thanks
hides
you're hanging around on spigot's discord on new year
im looking for a developer
?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/
Who the absolute fuck thinks “yeah I’m gonna name myself bidet”
Someone shameless
angry upvote
Here is the code:
{
if(state == CooldownState.READY)
{
sign.getSide(Side.FRONT).setLine(0, ChatColor.GREEN + "" + ChatColor.BOLD + "[Click Me]");
sign.getSide(Side.FRONT).setLine(1, ChatColor.GOLD + "To activate");
sign.getSide(Side.FRONT).setLine(2, ChatColor.GOLD + "trap!");
}
else
{
if(state == CooldownState.ALMOAST_READY)
{
sign.getSide(Side.FRONT).setLine(0, ChatColor.YELLOW + "" + ChatColor.BOLD + "[On Cooldown]");
}
else
{
sign.getSide(Side.FRONT).setLine(0, ChatColor.DARK_RED + "" + ChatColor.BOLD + "[On Cooldown]");
}
sign.getSide(Side.FRONT).setLine(1, ChatColor.GOLD + "Please wait");
sign.getSide(Side.FRONT).setLine(2, ChatColor.GOLD + "to activate!");
}
sign.update();
}```
The function is called 3 times. Immediately, after a short delay, and after a long delay, with each of the 3 cooldownstate enums (ON_COOLDOWN,ALMOST_READY,READY)
The sign doesn't consistently update visually in game almost always for at least one of the events, even though the function is called all 3 times with the right parameters (tested with debug.) And it is different which states the sign is updated to each time. so for example sometimes it would skip straight from the red on cooldown to the green ready (skipping the yellow step), but other times it will skip the green all together and go from the red to the yellow and never turn green. It just isn't consistent. Also, whenever I update the signs, I also update glass to the appropriate color too. **This always works, even when the signs don't.** It's just that the sign visually in game isnt updating, and I don't get why. I tried sign.setWaxed(true), no difference. let me know if you guys have any ideas
btw sign is import org.bukkit.block.Sign;
hey is it inteded behavior that players with some entity mounted on them can't teleport?
or did I mess up somewhere
isnt this a known spigot/bukkit weirdness
or maybe its the passengers dont tp with them
?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.
where/when are you calling that method from?
you really want me to post my 75k line codebase?
I don't know what part of it might be doing it
at all
no, only the relevant parts
if I knew what part is relevant in the first place I wouldn't have spent a day trying to figure it out
Write a tiny command that simply teleports the entity by one block or sth
does that work fine? or not?
I patched it for now, I'll have ot investigate it later because I'm getting a new ticket every 30 minutes due to this
So you fixed it? Great
How?
manually removing passengers
oh
also doesn't really work for all cases
idk why
whatever
it's patched for now I need to do the translation stuff now before the chinese community hunts me dwon even more
Ugly workaround but if it works, it works ig
Looks like the underlying issue is minecraft itself, ig
I never had problems teleporting entities that have passengers, maybe you should debug or sth idk
I added a stacktrace to see if it could track what is cancelling it, nope, it can not
it just returns cancelled with no further processing on the stacktrace
which is cool
You can try to print out all registered EventHandlers, I'm pretty sure you'll find the culprit there somewhere
I tried doing a search on the codebase for everything that cancels any event and I couldn't find it
nor could ai
idk man I just want to fix this so I stop getting pinged every 10 seconds
have you tried debugging it properly?
only up to the point where I figured out it was passengers causing it, which was pointless anyway because there was no real way to tell that was the bug in the first place, I just had to guess
You might be able to workaround that if you'd properly debug it - there must be SOME line of code (either in spigot, or in NMS) that causes that issue
but as I already said - if unmounting, TPing, and mounting again solves your issue - that's great, I'd probably do it like that too lmao
Technically yes if we are going by mojang code
uh intermittently, I'm switching between versions to also try to make this nms nonsense work
altough I'm also backtesting to 1.21.4, how far back would they have changed this?
?fork
SpigotMC maintains the Spigot server. If you are using a fork of Spigot (such as Paper, Airplane, Purpur, or other derivative works), you should seek support in the appropriate Discord servers.
alex do you think I just showed up here 5 minutes ago or something
Not sure i just rmbr seeing something about it
But my sense of time is so skewed due to way too many nightshifts
one hour ago you did
you haven't even tried debugging properly yet
I debugged it for 1.5 days until I randomly realized it was being caused by passengers, which was completely opaque in debugging
get spigot, write a minimal plugin that reproduces the problem
and then you can file a bug report on ?jira
but you seem to only wanna complain all day
and that is also how I remember you
I am trying to help, but you just keep trying to blame someone for any bug that you encounter
idk I don't like that
tbh I do the same sometimes
me blaming the world for my problems
I don't even know how you read the messages I sent to come to any of the conclusions you came to right there, I've been doing nothing but debugging for the past couple of days and I just so happen to not have time to sit down and drill down further now that I have a patch because other mission critical things have problems that need to be resolved right now
actually it does so happen all of the testing for the last couple of hours was on spigot 1.21.11 so that's definitely not it
hm
as far as I know in regards to teleporting, you need to dismount passengers and then teleport
and then remount
you can do these things relatively quickly
it just has to do with how the teleporting is handled and doesn't factor in passengers, also weird things happen when you try to teleport passengers without dismounting them as well
see that's what I was trying to remember frostalf
thing is I swear that wasn't the case for mobs? but I could be misremembering
I do vaguely remember something about teleporting mounted entities from 4 years ago
I believe as long as it was just only entities they should teleport just fine, the issue was when the passengers were players or entities mounted on players
since teleporting for entities is not handled the same way as it is with players
in the past from what I remember from 1.7 entities technically didn't teleport
not sure if that is the case now with uuid's
but in the past, technically the entity died and was spawned again lol as far as the internal code was
Everyone, why are all the classes in the chat package of bungeecord-chat versions 1.21-R0.3 missing? What changes were made? I can't find the ComponentSerializer class.
Is there any way to have breakpoints in a plugin? Like see exactly which path of logic is being taken?
A plugin, not mine, has a function call in a dozen places, it gets invoked at a certain point, and I'd like to see somehow, which function it is invoked from, if possible
or do i need to read the stack trace?
yes you can attach a remote debugger
i think paper has a guide on it somewhere
oh wait you mean another person plugin
maybe mixins?
pooper
you could use a profiler
to see where or what is calling a particular method
OH yeah thanks for the idea
hi, so basically i'm trying to port a plugin which adds tamable foxes from 1.20.1 to 1.21.10. it uses synched entity data in order to hold info about the tame status, i've been able to replace every nms call with the updated one but every time i try to tame one the client get kicked out with "Network Protocol Error". i've nerver used nms so i have no idea of what it could be, if you need the code this is the entity class which implements almost all the logic https://pastes.dev/gzveBwLenJ
What exactly does the error say, anything in client logs about it ?
Isn’t synced entity data, well, synced?
I don’t think the client will like receiving entity data it doesn’t know about
Why not just use PDC
ye you said exactly what I had on mind but couldn't put into words properly
what i tought but i excluded since older version used synced data but worked fine... maybe latest versions added a more strict check on synced data?
yes, packets did become a bit more strict in some ways
maybe this is one of them
oh well i just wanted to make a fast impl without chaning much the logic, but if that's the case, i think it's the only way to go
thanks
How do I suppose to retrieve the said tags?
EntityCategory org.bukkit.entity.LivingEntity.getCategory()
Deprecated. entity groupings are now managed by tags, not categories
Get the category to which this entity belongs. Categories may subject this entity to additional effects, benefits or debuffs.
Returns:
the entity category
I've tried LivingEntity#getScoreboardTags but the returned set is always empty? I just want to check if the entity is aquatic or undead, ...
declaration: package: org.bukkit, interface: Tag
Not sure why you would be directly depending on this, but there is a separate bungeecord-serializer now
Ok thank you.
I'm serializing a BaseComponent object to a String, intending to display the player's avatar using the format {"player": {"name": "in_Shiro"}}, but for some reason, I'm sending an empty string instead.
Hi all, not sure if you guys are following up on this, but my plugin heavily depends on the GameRules and because spigot and paper are apperently using different packages, with the altest 1.21.11 update EVERYONE is having issues
I really don't understand why all of a sudden they change this, but the impact is insane ...
Paper has hardforked off Spigot
Expect them to diverge even more over time
To support both you'll need to either use reflection or use a multimodule setup just like you would with nms
Yes this is what I'm donig now ...
But I'm having a hard time setting it up
Literally spent the whole night trying to fix it
When XGamerule
hmm?
Holy shit it's actually a thing
Yeah, I reworked my entire project already, but didjn't knew about this one, Thanks
I just don't like where this is all going that everyone is trying to have their own implementation
This is giving the entire developer community a very hard time keeping the plugins compatible ...
At this point just write everything in nms \s 🧠
🙁
yeah that's what I was thinking about
Yeah I'm very stuck right now, currently looking into ServiceLoader, not sure if I'm on the right track ...
If any tutorials for the multi module setup would be much appreciated
I'm not looking to compile for every single minecraft version btw
just saying
You can give XSeries a try
It's exactly what it's made for
(Supporting multiple versions)
Yeah I might be able to do that indeed, but any tutorial would be appreciated, I have to dive into it anyway
I really don't want to get hard dependent on XSeries
XSeries can be shaded no problem there
but if you want to know how to do it yourself I can guide you through that
I will if I still unable to find it, but I refactored my project for hte whole night
I believe I'm close to it working
i just have 2 jars, one for legacy(1.8.8, 1.12.2) and one for 1.18+
and i just merge changes from main
from another function,
3 times. it is inconsistent which times the sign actually changes, but the function is always called (like if I put message in the function it is always called), and glass always changes.
setSign(sign, CooldownState.ON_COOLDOWN);
setGlass(trap, CooldownState.ON_COOLDOWN);```
```new BukkitRunnable()
{
@Override
public void run()
{
setSign(sign, CooldownState.READY);
setGlass(trap, CooldownState.READY);
}
}.runTaskLater(plugin, 20 * trap.cooldown);
new BukkitRunnable()
{
@Override
public void run()
{
setSign(sign, CooldownState.ALMOAST_READY);
setGlass(trap, CooldownState.ALMOAST_READY);
}
}.runTaskLater(plugin, (int)(20 * (trap.cooldown / 2.0)));```
but like I was saying, the function is always called correctly, its just the sign chooses not to update oftentimes
Hi how do i teleport someone without losing the elytra velocity?
relative teleport I believe
wdym?
I am currently passing velocity and gliding status yet it resets the speed of the elytras
You probably need to reset those values a tick later
Though that still won’t be super smooth
I don’t think spigot has api for smooth teleporting
You need to do a relative teleport like steve mentioned
and yeah Spigot lacks API for that atm
Bukkit.getConsoleCommandSender() and minecraft:tp ~ ~ ~ 🤡
Call it a feature and move on /j
True true I agree
PR time 🫵🏻
no u 🔫
"Return value of the method is never used" Does JetBrains have any annotations to indicate that this is an API? Even though I don't use the returned value, could someone using the API also use it?
Wait are you looking to surpress the warning in the APIs code that the method is never used? Or when you implement it, are you looking to force that the return value is used?
ur lucky i signed my soul the CLA
Contract is for saying what types are returned/expected from params i think
unused is literally just the IDE saying this method isnt used ig
i'd just @SuppressWarnings or disable the inspection
i don't like the inspection since it's none of a method's business what callers do with the return value, if anything
the method is supposed to make sense in isolation
I just want to remove the warnings
SurpressWarnings then
there's also the ide-specific //disableinspection comment to do it in a given scope, but i don't remember the syntax since i use it so infrequently
Don't exists an annotation for this? I don't like this.
What you're describing is a warning, thats all it is.
does anybody know the SpawnReason for a dried ghast turning into a happy ghast?
Do you usually ignore or suppress?
There isnt one. its transform reason
or wait is it
i think the annotation is preferred since the comment is just ide-magic; the annotation is also seen by the compiler
though i don't think it's relevant here
that said there are limitations on where annotations can be put, so sometimes you just have to use the comment
do we have a material tag for all blocks that trees can be planted/grow on
I think it might just be the dirt tag
i'll give it a shot, ty
Otherwise check the source code for the SaplingBlock canSurvive
A path block is given the tag dirt. A tree cannot be planted on a path.
I think the same applies for farmland
VegetationBlock.java
protected boolean mayPlaceOn(BlockState state, BlockGetter level, BlockPos pos) {
return state.is(BlockTags.DIRT) || state.is(Blocks.FARMLAND);
}
it looks like it indeed can be placed on dirt, probably paths, and farmland
but i'm assuming farmland and paths revert into dirt from the resulting block update
somewhat awkward for my purposes but i suppose it's fine
Got a server 1.8 but supports all versions with ViaVersion
1.8 players can tab complete to see commands
1.21 player does "/" tab and sees nothing
i dont think 1.8 used brigaider
Nope, any work arounds?
are you registering your command in plugin.yml? If you are and they have permission it should just work
best workaround: Get a 1.21 server, usa ViaVersion+ViaBackwards, and 1.8 players (if you even want those) are still able to join
Yes commands are registered in plugin.yml which is the strange part that they don’t work!
does it work in 1.8 though?
Yup 1.8 players can see all commands and use tab complete sub commands for them
Then it's a ViaVersion issue
Eventually I need to upgrade but it’s 10 years of code …. Lots and lots of changing ….
probably a Via config issue
Good point I’ll ask via team
usually you do not have to change anything unless you're using "bytes" for block data etc
spigot is pretty good in backwards/forward compat
Got some NMS entities and codes that I really don’t want to touch too lol
Thank you
np
Someone knows whats wrong with jeff_media repo? I want to use the SpigotUpdateChecker in my project
@tender shard You did the forum post on that ig
It's down
yeah i found an alternative
is it possible to display a chosen pakcage instead of the whole tree which takes a lot of space and is annoying in intellij idea?
i wish i could kinda open a specific package though
guys someone know a "hide" plugin? like, you use /hide and your nick get scrambled
I think there is a method to put §k before players name
how?
bro just search it
xd
its rare to see someone use "xd" and not being polish
im persian and i commonly use xD or XD
Hey
does anyone have any idea
why "execute as @a <command>"
ends up in the command receiving a console sender..?
Yeah that doesn't sound correct. Should only be players
the command here would be "psudo"
Yep
just confirmed with a much simpler command
"execute as @a at @s run whoami"
returns ConsoleCommandSender
oops. I was using paper
smh..
Spigot straight up doesn't let you run plugin commands using /execute
so not much better ig but not unexpected behaviour
💀
Block placedBlock = placeBlock(frame.getLocation(), Material.VAULT);
since GameProfile is immutable on newer versions (since its a record) what is the method used now for GameProfile name field update
do i recreate the profile?
Is there an easy way to get the location of the block - 1 or shifted by a transformation
Without creating an entirely new location
nvm i'll just do the math
dumb question
What r u asking exactly
there is a subtract method?
Block placedBlock = placeBlock(frame.getLocation().subtract(0, 1, 0), Material.VAULT);
oh shoot yes that was exactly what i was looking for
a way to do it inline
problem solved
@short pilot Your life matters, you're doing really good, never give up.
that was very kind, thank you
@short pilot Just letting you know I've donated to children in Africa in your honor
What do children in africa have to do with this?
The guy who makes spigot is an african child
duh
why would we lie, and also make a donation to a legitimate charity?
Muntambe dewolo (md)
Oh thats cool
5 is the years in prison for machette posession
Trying to be like vim 🙂
They also help poor childrrn in uganda
I KNOW
BASSSEDD
but the original charity closed right?
because vim creator passed?
lmao
Does anyone know how I can broadcast a mini message component in a spigot plugin
// Block the vanilla message from being shown
event.setJoinMessage(null);
// Broadcast the custom message to the entire server
Bukkit.broadcast(colorizedJoinMessage);```
Im trying to do this but it says the broadcast function only takes a string
I think the adventure bukkit platform has an option for that
Otherwise you need to deserialize it to a plain string or use NMS
okay, thank you ill try
6 dollars nice 😂
it did??? naww
I don’t control how much I’m paid? Atleast I do it.
thats kind
Im searching for someone that can make a custom resourcepack work on my server. models are already made just the resourcepack needs to be made and the models connected to the model data. WIll pay if it works.
I'm down
Look messages
Any history buffs in here who remember when the plugin channel name length limit was increased from 20 chars? I am curious to know whether that was a hard protocol limitation, or an arbitrary one
Trying to backport something to a server that is stuck in 2011
Ie. this value
is there a way to make a player force swim / crawl without client side blocks? cuz i also want em to be able to jump
Hm, how do I use BuildTools to compile a custom version of Spigot if I alter this file? Even with --dev --dont-update it seems to overwrite the files during compile.
I guess don't use BuildTools
u just do it from the Maven project itself i think
Yeah that's what I did 👍
To answer my own question: The limit is probably a real one. Increasing it in code does allow plugins to register longer names, but those channels don't function. I made a custom version of the mod I'm trying to talk with that uses a shorter channel name, and that does work
is there a way to reduce name tag render distance?
other than teams
or completely hide nametags behind walls?
Theres Player#hasLineOfSight(Entity)
That should tell you if a player can physically see someone, I don’t think it accounts for viewing direction but rather if the player plausibly could be seen by the player if they turned. Which is fine because that’s all you need for nametags
And I think you can use Teams to do the name tag hiding stuff
Guys, I need some help here. How do I get Luck Perms to recognize who have . at the beginning of their name? (bedrocks)
not sure if luck perms supports it, but an alternative is re-naming the players without the .
I don't think you can?
Floodgate needs a prefix
The player is a bedrock player in this instance, they do not have a Java UUID
just because they connect with a specific name, doesn't mean that is the name that must be shown or used
they have an XUID
It can be disabled in floodgate or changed to a different character
is it recommended to use optional for this?
Bukkit.getScoreboardManager().getMainScoreboard();
the class Optional?
the null error is really not gonna trigger like ever
the server has to load without a world afaik
@Optional?
oh wait no i mean java.util.Optional<T>
util optional
ye
whats he asking tho
getMainScoreboard is marked as nullable
ohhh
or was it get new scoreboard
maybe both
declaration: package: org.bukkit.scoreboard, interface: ScoreboardManager
on newer versions both are @notnull
ohhh
it's the getScoreboardManager
my bad
yeah
so its fine if a leave it as is?
i do leave it as is
great thanks
it should affect you if you try to load it onLoad i think
but if you want to be sure, you could use optional
I am just using it to register a team. so if the scoreboard loads prior to that there shouldn't be any problem.
Pretty sure Scoreboards will not be available in onLoad
They are stored in teh world files and those are not loaded yet
Hi everyone, I want to make the player's face displayed in the new version's {"player": "id"}. How do I do this? I'm using Player#spigot's sendMessage, but it only sends an empty string instead of other content.
What did you try
sender.spigot().sendMessage(*ComponentSerializer.parse("{\"player\": \"id\"}"))
use text components
If you want to show a player you use the ObjectComponent with a PlayerObject
oh there you go
https://www.spigotmc.org/wiki/the-chat-component-api/
https://javadoc.io/doc/net.md-5/bungeecord-chat/1.21-R0.4/net/md_5/bungee/api/chat/objects/PlayerObject.html
https://javadoc.io/doc/net.md-5/bungeecord-chat/1.21-R0.4/net/md_5/bungee/api/chat/ObjectComponent.html#<init>(net.md_5.bungee.api.chat.objects.ChatObject)
The home of Spigot a high performance, no lag customized Bukkit Minecraft server API, and BungeeCord, the cloud server proxy.
Looks through those links. Should tell you what you need to know
Can't I use a parsing method? I provide JSON format, and then I parse it into a PlayerObject.
If you want to you can
but you'd have to provide a valid component
which your json string is not
Also I'm not sure why you have a * in that method call as well
I'm using Kotlin syntax. The asterisk (*) is a parsing operator that turns an Array into a collection, which is equivalent to a String[].
The main requirement is backward compatibility; it needs to support multiple versions simultaneously, as changes in newer versions may render backward incompatible.
hm? String[]??
You do not want a string array you want a component array
I assume that's what you mean though
To be precise, it's a variable parameter, which is a String...
Anyways you need to fix that json of yours. It's not a valid component
if you're sure it's a string then that's wrong
Strings do not contain the required data to show other components than text
To be precise, I want the same ComponentSerializer#parse method as R0.2 for fast JSON processing.
I don't understand what you're trying to say 🤷♂️
In summary, I want a component that displays the player's head skin, but it also supports parsing a JSON text content I provide, such as {text: {}, keybind: 'key.inventory', translate: 'addServer.add'}. It will parse this content without me having to construct a class, just like ComponentSerializer.parse(text).
So why can you not use the component serializer?
Because it disappeared in R0.3+, I couldn't find this content.
It still exists
It just got moved from the main chat module to the serializer module
But I couldn't find it when I opened the JAR file, which is strange because it runs normally without any errors, which is why I'm asking here.
I directly imported net.md-5:bungeecord-chat:1.21-R0.4, did it split the content into separate parts?
To be honest, I didn't understand your last sentence.
You should be using maven or gradle to fetch the Spigot API and it's dependencies
Not depend on the spigot-api and bungeecord chat jar files through your IDE
Yes, as you said, I referenced it through Gradle, not by importing the JAR file into IntelliJ IDEA.
I used to do that in Eclipse IDE back in 2016-2020..21
I didnt even know about maven or pom.xml back then
XD
i still remember having to download the api jar and javadocs jar and my downloads folder was full of them
They could use the server load event for this
but generally yes, in onLoad most times the server has not finished loading the world
huh, i always wondered why Scoreboard stuff was nullable
forgot plugins can do stuff before worlds load
kotlin people, do you think it makes sense to have each GamePhase be a coroutine in a minigame?
so I just do phases.forEach { it.start() } for when i need the phases to run sequentially?
also wtf is intellij doing filling up my whole /home partition to the brim for few seconds before deleting everything again?
k@fedora:~$ df /home
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/nvme0n1p6 47159296 46865224 8 100% /home
k@fedora:~$ doas du -ah / | sort -rh | head -n 20
^CInterrupt
k@fedora:~$ df /home/
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/nvme0n1p6 47159296 29365188 16565836 64% /home
like what
phases.forEach { it.start() } ?
if start is starting a new coroutine, then wouldnt that imply all routines fire them simultaneously?
I imagine u need something sequential, as it is a minigame?
or is start being held onto?
I don't think it just "makes sense", i think this is how its done?
it suspends until the phase ends
my idea was to have one CoroutineScope for the gamecycle, that runs all the phases' start() function sequentially and ideally another CoroutineScope for each phase so i can bind event listeners to it
and then cancel the coroutinescope of the phase at the end of it
to kill of the listeners
Probably bad wording, i mean the start function is suspending and not that its a new coroutine
soudns gud
#help-development message Consider this though @robust helm
you mentioned binding event listeners to the scope i think
its good to keep in mind that cancelling a scope will not unregister a listener
so, i think you'd be left with something like:
fun CoroutineScope.bindListener(foo: Listener, bar: JavaPlugin) {
Bukkit.getPluginManager().registerEvents(foo, bar)
this.coroutineContext.job.invokeOnCompletion {
HandlerList.unregisterAll(foo)
}
}
Unregistering listeners always feels like an anti-pattern to me. You can keep listeners registered, and simply delegate the events to places where they are needed, without any real penalty.
thanks :)
you mean having if (currentPhase == this) at every listener?
or have a whole event bus on top of the bukkit one?
if by whole event bus you mean a single class, then yeah
I have a single listener for all bukkit events, and it just sends the events to all classes that want it
and sometimes those classes either exist or don't, and sometimes they check if they need the event or not within the handle method
but it looks like you are just working on a state machine
the controller or whatever should be forwarding events to its current phase
it should not be any harder than that
🤔🤔🤔 this does make sense
ig yeah but i imagine it get a bit more complex with priorities and ignorecancelled as you need to reimplement that yourself
maybe, I have never ran into priority issues
you would only have 1 class from your plugin that is handling the event in actuality
I mean thats what I would assume
hmmm
then i have something like
public void <T> registerListener(phase: Phase, Consumer<T> handler) {
listeners.put(phase, handler);
}
in EventController?
does it need to be more complex than this?
eeh ig ill do smth like
suspend inline fun <reified T: Event> CoroutineScope.bindListener(
phases: Set<Phase>,
ignoreCancelled: Boolean = false,
priority: EventPriority = EventPriority.NORMAL,
noinline handler: (T) -> Unit,
)
and check for the current phase before passing the event to the handler
no thats braindead too, then i wouldnt need coroutine scopes
what is the registering for
wdym
who are you registering these handlers for
I get that you have to register them to bukkit to it knows to call those handle methods
each phase calls registerListener(this, <handler>) in its constructor
and the eventcontroller then passes the events to the current phase's handler
if youre refering to this
I don't write kotlin
why does it matter if a phase is registered to an event
i mean i could do something like
void onJoin(event: PlayerJoinEvent) {}
for each method and only override whatever i need in the phase
but to reduce boilerplate I'd just use generics
and then register with registerListener(phaseListener: PhaseListener) or something ig
in EventController:
void onEvent(event: Event) {
var handlers = listeners.get(event.getClass()).computeIfAbsent(ignored -> new HashSet<>());
if (handler.phase == gameCycle.getCurrentPhase()) handler.handle(event);
}
and listen for all events in a listener
does that work?
im not sure
I have never tried doing it like that
how do you do it?
hmm
and my phases only really use like 6
I generally just forward the event to the current phase regardless
and then the phase either does something or not
I mean yes, you do have more boilerplate in the form of an abstract class or interface that has handle functions and a controller that is passing events along, but in my case this is done by another class so the controller itself is not getting cluttered, and also that means that each phase is very clear in what its handling since im just implementing the handlers the phase needs
and then the listener does controller.phase.onJoin(event) or whatever
trueee
doesnt sound too bad
i could also do something with annotation
in some gamephase:
@Listen(PlayerJoinEvent.class)
void onJoin(ev: PlayerJoinEvent) {
// TODO
}
and then register(phase: Phase) where it iterates over all methods and checks for @Listen annotations
its more naive but its way simpler and easy to understand imo
though this is probably more complex than needed
the real question is how much are the phases relying on events
i guess but im worried that if i want to extract my api to a separate library and someone wants to use custom events, it wont work
or would require some hacky method different from all other events
hmm
currently a lot, each phase has its own listeners cancelling the events
if you are planning to write a library out of it, then your approach is probably better
given that listening to Event actually works ofcourse
that would be something to try out
i could also extract the whole event stuff into Toggles so that i have e.g Toggles.get(PvPToggle.class).disable() and .enable() at the start and end of each phase
again that depends on what the phases are actually doing
if they are just listening to events to cancel them or not
then yeah that sounds fine
if you want them to actually trigger stuff based on the events, idk if the toggles work
everything sounds fine smh. Toggles reduce code duplication as i dont need my PreparationPhase and PvpPhase to have its own listeners
but also this toggle system seems kinda overcomplicated
true
or i mix them and have global listeners for HungerLevelChangeEvent cancellation and such, and phase-specific listeners for smaller stuff like BlockBreakEvent cancellation in CountdownPhase
not a fan of the toggle idea
my advice for writing a library is always to imagine that you are the one using the library, what would you like your code to be like in the simplest way possible to allow pretty much everything you want
and then determine the structure you need out of that
all this registering stuff is useless if it doesnt align with how you would use the library
i.e. if you were to use this, how would you be creating new phases? stuff like that
maybe you just need like a component system or some kinda builder to create a class with listeners the phase needs
but maybe you need to have a registry system to allow custom phases to be registered and register each handle automatically
then its a question about if you want this registering to happen on the fly as you switch phases or if you want to register everything up front, etc
current approach is to have a GameCycle interface for nextPhase(), previousPhase() and have implementions like LinearGameCycle
and the LinearGameCycle takes in a parameter with an array of phases
but the user is free to implement his own GameCycle
so you need a way to listen to any arbitrary event that exists, even custom ones presumably
this falls out of the race as it assumes a listener is removed after phase end
but e.g damage is disabled in both the WaitingForPlayersPhase, the CountdownPhase and the PreparationPhase
i feel like ill have to use Toggles, then have some
interface Phase {
Set<Toggle> getEnabledToggles();
]
so at least its declarative and its clear what toggles is active where
how would you be able to add custom toggles of your custom events
that the class thats using getEnabledToggles is actually able to do anything with
implement EventToggle<MyCustomEvent> which has a handle(event: MyCustomEvent) method
aah i hate this
I think firstly you should try if you can blindly receive any event by listening to Event
also this is a bit difficult cause Toggles may have constructor parameters, so i cant just have a global toggle registry
but instead i need to either instantiate a new toggle in each phase or game.toggles.computeIfAbsent(PvpToggle.class, ignored -> new PvpToggle(/* repeat constructor parameters to be fully declarative*/)
and if i do it non-declarative you need to keep track of all enabled toggles by reading the code which gets especially difficult with non-linear gamecycles
but anyways, if you cant just listen to all events at once, that means you very likely have to make your phase an EventListener
which would require some kinda way to either unregister.or block the event beforehand if its not the active phase
unless there are exceptions where a phase needs to know about an event even though its not an active phase
the way this is done with statemachines is in your case by having a concrete game cycle to that handles specific events and then create your phases to use those events, but this is a nightmare of boilerplating probably
i dont even need to listen to all events at once if i do register<T extends Event>(clazz: Class<T>, phaes: Phase, handler: Consumer<T>)
true, so would you check whether the clazz is already being listened to by the cycle?
in this method I mean
like if you can implement this method properly that is all you would need
not neccessarrily but yeah
PerWorldPlugins did it somehow..
it is doing some heavy fuckery with the handler lists https://github.com/TonimatasDEV/PerWorldPlugins/blob/master/src%2Fmain%2Fjava%2Fdev%2Ftonimatas%2Fperworldplugins%2Fmanager%2FListenerManager.java
beautiful
basically rerouting every listener to its own event
might not be a bad idea for you xD
maybe
but idk
More like another use-specific event bus on top of the Bukkit one. Preferably one that scales O(1).
but kinda magical that it can be done like this in the first place tbh
and if it doesnt, noone will notice
flawless
people will just be confused why their events are broken on their remapped event listeners
not my problem (i will be the only one using the plugin/library)
but imagine if you were to use this same trick, to check if a listener is a game phase and if so you can wrap the event and not handle it based on the condition (if the phase is active or not)
but even then I would probably just wrap it in your register() method
instead of after the fact
oh this does make sense too
man but i need to suppor this
ill have a coffee
only thing im unsure about is how it actually calls these events
I would probably maintain something like a Map<? extends Event, Consumer<? extends Event>> in my minigame instances and then pass the events to them. Messing with the handler, and even reflecting into it, seems like an unnecessary and error prone approach.
yes but how would you use this with custom events, like do you know if you can just listen for Event and delegate from there?
you dont need to if you have a register method that takes in Class<? extends Event> as a parameter
or would you just add methods for them in your minigame implementation
you can just do PluginManager::registerEvent(eventClazz, /* other params */)
yes but then how do you start/stop listening to events and how do you filter for the current phase?
Sure, but this way you need to constantly (un)register events on runtime
alternatively you could use beans
When the MinigameManager doesnt have the Minigame anymore, it wont pass events to it.
I imagine you have a MinigameManager that maintains a Map<String, Minigame> or something similar.
You never have to worry about starting or stopping to listen. Every event is just passed to all minigames. If the minigame is not in the map
anymore, then it wont receive any events.
If you minigames are constrained to domains (Like a World or BoundingBox), you simply filter by domain first.
All the logic is done by the minigame itself. A minigame could have phases, and maintain a Map<PhaseType, MinigameStage> itself, and then simply pass the event down to the Stage, which itself contains the Map<Class<Event>, Consumer<Event>>.
public abstract class MinigameStage {
...
}
public class SomeJumpAndRunStage extends MinigameStage {
public SomeJumpAndRunStage() {
this.registerEventHandler(PlayerToggleSneakEvent.class, this::handleSneak);
}
private void handleSneak(PlayerToggleSneakEvent event) {
}
}
never have i ever needed stages in my minigames
my plugin is a minigame, it has 3 phases, pregame, game and postgame
yeah that's about it
I usually also dont use a "Phase" system, since the lifecycle of minigames is always the same. BuildUp, Lobby, Play, TearDown
i planned on using one for waiting for players, then for the countdown before game start, then preparation phase where you get basic equipment, then pvp phase where pvp is finally activated, then deathmatch, then postgame and finally teardown ig
for most minigames, the play stage handles everything and has flags to determine when to spawn diamonds or whatever
but I think this is mostly just a system that the individual minigame could create if it was this complex
I think you should probably stick to the 3 or 4 "phases" that are minigame-agnostic, and then handle all the specifics, like getting equipped etc, in an abstraction layer within your minigames implementation.
the general event code in this case would largely be the same
i think i should give up coding
for now
😩
I personally dislike Minigame development. It has been done so many times already, making it a bit dull.
ive never finished a proper minigame, only FFas lol
in my 3 years of spigot development
And almost no server needs minigames. It is almost impossible to make a good argument for playing on a minigame server that doesnt already have around 50+ people on it.
also what else would a player enjoy
I am still trying to think of another plugin idea but vant come up with anything because its been done by an army of developers
the minigame plugin I made is primarily designed to be used to just play with your friends, not a global online minigame servers, as those servers usually hire devs to make it fit the network they want to have
i do mine because (1) i have nothing better to do (2) i want to make a server network and (3) i want to learn
server network requires some resources. It is a bit hard when you don't already have those resources
capital being the primary one
power isn't really the issue in that regard, rather bandwidth
ill ban everyone
🧠
no but i dont really expect players, i can get a host if i do though
Im personally working on a citybuild server right now, where you have a full blown skill system, and the farmworld gets progressively harder with random encounters, and bossfights the further you go from spawn. And with clans that can level up, and enable rune slots. And mounts, and followers, and a ton of other stuff. A ton of fun to develop this.
Number go up = good 😄
the hardest part about this is getting a playerbase xD
oh damn
there is still room in the minigame space for minigames. Most who make minigames do so in respect with teams. I don't see a lot in way of minigames for the individual
its like an anime world that you get reincarnated to by being hit by a truck
Its for an influencer. The old server is already well visited ^^
Having someone to promote a server is almost more important than the actual content.
i prefer simple games though, bedwars is the most complexity my brain can enjoy
yeah
ah yes this is the best case by far, finding an influencer that wants a fun unique server and has the outreach to actually make it be played
I think this is like a dream for many plugin devs haha
Yes, you cant imagine the dopaine when i come on the server to announce we are restarting for an update, and you get bombarded by several dozen people, asking what new stuff you wrote 😄
getting attention is always cool xd
I suppose if you never experienced it. I have had a few plugins advertised by influencers before and I will say this, I appreciate it more when its the influencer that decides to do so without me having to be involved in it. IE, I didn't ask them or have any correspondence for it.
My public are probably all dead by now... havent touched them in years
its just a different workflow too I imagine
writing for a single server compared to writing for any server
Nvm... this one still sees like 1k. How is that even still working?
Yeah mine definitely are lmao
probably all thanks to spigot api xD
Well, one of my plugins died thanks to Mojang
and then another one of mine still technically works if you are on some old version I suppose
however its helped spawn derivatives that perhaps may be better
But if you are looking to rewrite something, i regularly get messaged by people that want me to update this one. 😅
I dont have the time, but i think there is a demand from a few people for this.
https://www.spigotmc.org/resources/advanced-machines.71731/
My plugin, HoloAPI and the current popular competitor Holographic displays are the primary reasons Armor stands existed they way did. But that update killed my plugin unfortunately.
I am glad though that Mojang came out with Entity Displays to replace what armor stands were being used for lol
oh that looks really good, reminds of the immersive engineering mod
i do be intressted in the source code but i'll probably loose motivation pretty quickly
Holographic displays is dead. And one of the reasons why i had a few weeks of rage-fuled refactoring sprees, since the prior devs code looked like he was just starting to understand some code from youtube tutorials. Im so mad when i hear this plugins name, still.
oh it finally died? Never said their code was great lmao, but they were the only competitor to HoloAPI despite their terrible code.
whats your plugin then?
the only holo plugin i ever used (as an api) was decent holograms
oh HoloAPI is your plugin?
but it makes sense that "mod" plugins for a lack of better term are in demand, especially now with whats possible with plugins I can see a lot of ways that mod ideas can be ported over to plugins
slap on a custom resource pack and you can pretty much do most things that mods do
i hate when servers make me download a resource pack
Nah the dev that used this API was bad. We didnt have an abstraction layer or hooks so i could easily swap out the plugin.
It had a ton of hard-coded, stubborn, childish code, with classes that where 2k in lines, copy-pasting 90% of the code to make small changes every time. He didnt even use an API for GUIs. Im speaking, dead-ass, one listener per gui with
if(event.getClickedSlot() == 4) {
// Deep nesting and 100 lines of code
} else if (event.getClickedSlot() == 5) {
// Another pile of spaghetti
}
You couldnt make that up. And it ran for like >200 people on one point.
Felt like the yandere-dev of spigot had his fun there.
Thats the reason why im re-writing the server from the ground up right now. Since we where hard stuck in 1.19, with no way to update this.
Does yours use TextDisplays by now?