#help-development
1 messages · Page 1838 of 1
yea
Why would you want to do that anyways
the only possible way would be to use a fallback server w/ like bungee
Is there an already available database for use in spigot like an h2 instance or something? Or do I gotta pull that in as a dependency. I guess a better question, is there a native way to store persistent data before I go down the db route?
files đ
Lolol I did want to avoid writing to files for speed reasons
Regarding copyrights when developing a plugins with spigot, am I allowed to make javadoc that contains my author name on my plugin ?
Of course you can, its your plugin =]
Spigotâs implementation of YAML is all cached in memory. So you could set your plugin up to write every so often, or at shutdown.
Hmm that could possibly work. There may be many many reads though, as I want to keep track of "cooldown" on an item per player
Are you using 1.14+? Because if you are, you can do that with the PersistentDataContainer.
You wouldnât even need files
I am indeed. Problem is, I put a persistance data container on the item to keep track of "time left". But I still need to update it when the user "hovers over the item" or the timer ticks
I did actually find this, may be an even better solution
https://wiki.vg/Protocol#Set_Cooldown
Well, I donât think a hover event exists, but simply updating the value should cause the item itself to update. If not, you could always Player#updateInventory()
any guy have item builder?
I think thats what I shall do then
public static void doSomething(String s) {
}
How do I use this in other java classes?
I think I still need some sort of data store server side to determine "which players are on cooldown" though
That could also work, but there is an api method for that on, I believe ItemStack.
ClassFileName.doSomething("abc")
You need to import the class
You wouldnât need to use packets
Ohh that would be amazing lol I hate working with packets
Is BungeeCord supposed to autocomplete commands automatically?
When I import it I cant use the static
The method is literally called setCooldown. Not sure if itâs part of the ItemStack class or the Material class.
code?
Well holy shit lol. I was utilizing custom model data to show a "cooling down" sprite. But I may just use the native cooldown bar
fine
Wouldn't need to keep track of stuff server side, just slap that setCooldown and call it a day
Ahhh yup this aint gonna work for me. Unfortunately the cooldown operates on the base material, not the specific item stack.
Looks like custom solution is back on the table boys
how to set the mob?
ItemStack spawner = new ItemStack(Material.MOB_SPAWNER);
package me.mrkboy8.wintergames;
import me.mrkboy8.wintergames.globalEvents.asd.sad;
public class sdf {
sad.
}
no autocorrect
Here are some links to get you started on learning Java:
- https://www.codecademy.com/learn/learn-java
- https://www.sololearn.com/learning/1068
- https://www.learnjavaonline.org/
- https://programmingbydoing.com/
- https://docs.oracle.com/javase/tutorial/java/index.html
The last one is the only official one, however some of those concepts assume that you already know a bit about programming.
ok
you can use into a function ( public void )
try:
package me.mrkboy8.wintergames;
import me.mrkboy8.wintergames.globalEvents.asd.sad;
public class sdf {
public void abc() {
sad.doSomething("ABC");
}
}
ok thanks!
try
how do i add nbt data like "ASPECT_OF_THE_END" or "SUPERIOR_DRAGON_ARMOR" to items and retrieve it on 1.8?
do plugin message channels (in a bungee) need the bungee to know the channel? or can serverA message serverB directly?
afaik nbt on 1.8 requires nms
https://www.spigotmc.org/threads/tutorial-the-complete-guide-to-itemstack-nbttags-attributes.131458/
ty
np
Hey, if you havenât resolved this issue by tonight, I can help after work. I got 5 mor hours, but I have a project that uses the PDC to update lore on ItemStacks.
Appreciate it! I will just be fiddling with stuff. I def could just "Get it working", but I wanna keep things lightweight
do i have to put something in my pom.xml for nms to work?
if you use "spigot-api" change it to "spigot"
ok
BUT!! if you don't use abstraction or reflection your plugin will not run on different versions
- you need corresponding mc version compiled with BuildTools.jar on your pc
im very confused
Isn't there nbt API for 1.8
Hello guys, i have a problem with my plugin.
in the Timings Report, the avg parameter for my plugin shows up red (I mean it looks like avg(75.44ms per - 2.32ms/0.03 per tick) and it shows me that it's supposedly because of my 3 eventhandlers, but I don't know what to do about it (and I using purpur with 1.17.1 version on server)
my code for one of them (which also shows up that it's because of it) looks like this:
@EventHandler(priority = EventPriority.LOW)
public void onInventoryOpenEvent(InventoryOpenEvent e){
if (e.getInventory().getHolder() instanceof Chest || e.getInventory().getHolder() instanceof DoubleChest){
Chest stt = (Chest) e.getInventory().getHolder();
}
}
What can I do about it? (I can also show a piece of code for the other events)
Not that people should be using 1.8
Run BuildTools with the âcompile craftbukkit flag for whatever version you want to be able to use with maven.
how to make a spawner?
I am a bit confused, if i return a FileConfiguration to a string it should return a string containing the path and the root, i load the file once and after that if i log fileconfigururation to console it shows that the path is empty but if i return the file to console it returns the corect path đ
[20:05:30 WARN]: [MyPlugin] plugins\MyPlugin\exampleFolder\exampleFile.yml <- This is File object to console YamlConfiguration[path='', root='YamlConfiguration'] <- This is FileConfiguration object to console
- You need at least once build the version via BuildTools.jar, like e.g. if you're using 1.8, you should at least once runned BuildTools with 1.8
- If you don't use reflection/abstraction your plugin will ONLY run on that mc version, that you used in your pom.xml
- You may use ready external APIs to avoid f*cking with NMS
Well you could store the holder rather than getting it 3 times but this doesn't look like it would impact performance
thanks
The path is not the path to the config on the filesystem
wtf
okay, thanks
It's the path of the ConfigurationSection within the config
NMS can be used to do awesome things
Which, for the config root, is an empty string
Is there a way to mock a large data load for /timings? My server only has a few friends on it, but I want to stress test this plugin with a few hundred.
welp so I made my first command plugin to give myself items and I understand the code behind it but it still makes me feel terrible about my current skills in programming for some ungodly reason
Sure, but itâs not like people expect perfect code from beginners and if they do, they are extremely out of touch from reality.
Youâll get better with time.
help
The spawner disappears when I put down '-'
1.8.8 Spigot
lol
plsss
Can you give more details please
Lolol
help? '-'
Bruh you didn't give em enough information to help you
are player stats saved clientside?
We need specifics. Explain what you did to end up with your problem.
Are you really this dense
Go learn what a help vampire is and then stop being one
Wait, thatâs a term?
Anyone know?
I think they're actually saved in the world
Isn't there os.sleep or something
This is very easily googleable
And I don't know why you're asking for Lua help in the spigot discord
?????
I'm not sure what you doin here with lua lol but yea use os.execute to execute your os sleep command
Wait() doesnt work
How would I do that>
.-.
i created an itemstack, however when i try to put it it disappears.
The lua discord server isn't English.
cuz this is help-development... well if they using Lua for something then it applies.
people need more information than "the spawner just disappears. 1.8.8" to help lol
Make the spawners stay there, if its a block issue figure it out.
I don't know much of java.
'-'
Hey, how would I apply the glowing effect for every nearby ArmorStand to the Player?
Have you tried google?
os.execute does exactly what it sounds like, if you are on linux it will run terminal commands
if(command.getName().equalsIgnoreCase("spawner")) {
if(!(sender instanceof Player)) {
sender.sendMessage("§cERRO » VocĂȘ precisa ser um player!");
return true;
}
Player p = (Player) sender;
ItemStack testSpawner = new ItemStack(Material.MOB_SPAWNER, 1);
BlockStateMeta bsm = (BlockStateMeta) testSpawner.getItemMeta();
CreatureSpawner cs = (CreatureSpawner) bsm.getBlockState();
cs.setSpawnedType(EntityType.BAT);
bsm.setBlockState(cs);
testSpawner.setItemMeta(bsm);
p.getInventory().addItem(testSpawner);
}```
Yup
what's the difference between File#mkDirs() and File#getParentFile#mkDikrs()?
pass it a string thats a straight up command to sleep
I'm not using linux
when asking for help:
- explain the problem and give plenty of details
- say what you have tried already
- don't act entitled and cooperate with the people you are expecting help from
Same applies to windows though
I just don't know what windows sleep command is
or its args
I'm looking for a wait command on lua
dos batch commands...
When I go to place a spawner that I gained from this command, it disappears, it is not placed.
Lua doesn't have one
You can do getNearbyEntities on the player
You have to emulate it with os sleep
Iterate over them and check which ones are armor stands
y'all got like a million different things going on rn
@quaint mantle make a thread
in this chat
fixed
And then you can apply glowing to the ones that are
Koddy has done everything wrong
btw 'timeout' is the command you are looking for but there is no precision with it, so like timeout 5 is anywhere between 4-5 seconds
Don't be like koddy
the mob don't spawn
how do communicate with the spigot console ?
else if (!(commandSender instanceof Player)){
}
For example I'm trying to send an error message if anything other than player is trying to call the command
- asked for help with no information
- didn't give any details when asked
- kept asking for help without elaborating
- said "fixed" but didn't explain how
commandSender.sendMessage
Bruh I think kody be trollin lol
Yeah sendMessage works on both
if ya just doing this for testing ya can just global broadcast and just brainfarted on that fnc
brainfarted on that fnc
the name
so if the command sender is a player, only the player will see the message ?
Yes
great thanks
Itâs the sender of the command, implying one
already learning more that's nice
Can we get a rule against help vampires so that we can mute people who just spam asking for help without giving details and clog up the chat so other people can't get help?
just report'm spamming and done.
Last question for tonight, I don't want to bother too much
Ask all you like so long as you ask respectfully
So :
if (e instanceof ArmorStand) {
Apply glowing
} else return;
}```
Ok thank you
Don't return lol
Oh
Get rid of that else
else if (!(commandSender instanceof Player)){
commandSender.sendMessage("Error, a player needs to call this command.");
return false;
}
return true;
I'm returning false if the command sender isn't an instance of a Player but I'm not sure I understand the way returning works in public boolean onCommand()
That would stop after reaching one non-armor stand entity
Ok, thank u đđ
I believe it shows usage if you return false and if the usage is defined in your plugin.yml
But it's been forever since I did commands that way so I could be remembering wrong
I'll go deeper in the docs then
Ok, so Iâv had weird experiences with this, but generally you want to return true when it comes to commands.
Sometimes if you return false, and have your plugin.yml set up properly, you will receive the error message from the plugin yml for that command.
I would recommend abandoning the plugin.yml way of doing commands as soon as possible
It's ugly and horrible
I'll read more into how commands should be done most of the time for tonight and make some javadoc so I don't get lost when I open the project tomorrow
thanks a lot
Mmk
Once you feel comfortable with commands that way start looking into command frameworks
command frameworks ?
command frameworks are the bomb
Is there some event like (PlayerCommandPreProcessEvent) for console?
Thereâs the normal command handler. Just check if the sender is an instance of ConsoleCommandSender.
Not to my knowledge
Want it for all commands not just for plugins
smth like block console from writing some commands
for ex. gamemode and stuff
mby the ServerCommandEvent
?jd
Why would you want to prevent the server from sending commands
bcz of my friend always cheating with a console commands on a survvial server and using gamemode for giving themself stuff
so only for private use
That might work. According to the Javadocs
This event is called when a command is run by a non-player. It is called early in the command handling process, and modifications in this event (via setCommand(String)) will be shown in the behavior.
It also has use cases listed on there.
Conditionally blocking commands belonging to other plugins.
Should call setCommand("say hi") so that every command is replaced with saying hi
is there a way to change priority of my plugin be loaded (calling onEnable) besides of set depend?
so I want my plugin be loaded as early as possible (optimally the first one)
Yes
load: STARTUP
Yes
let me try it out
Gonna ask again I think it got buried. Is there any sort of mocking or stress testing strategy I can do for my plugin to test it on hundreds of players? My little server only ever gets like 10 at a time.
I know about /timings but I need to see how it works with a large number of players
ya that's works perfect, thanks
Not that I know of
Simulating player activity for hundreds of players at a time would be a stress test for even the strongest of computers
Yeah haha thats fair, I just wanna see how it would perform on a "large server". Its hard to tell if my approach just utilizing hash maps for storage is scalable
@trail lintel look into https://wiki.vg/Client_List or something
đ
Determine the runtime complexity
And figure out the overhead of every method you're using
is there a difference between file.mkdirs() and file.getParentfile().mkdirs()?
Hey! Is there a way to check if a server is running Paper or Spigot?
similarly to /version
Is their a plugin where i can connect a BungeeCord server to a discord bot?
does anyone from here use Jetbrains notnull and nullable annotations here
also how do i get a list of online players
Bukkit#getOnlinePlayers
that returns collection but ok
do you have docs link?
yes why
Never used in plugin development
But in android studio yes
is it me or do they check the passed arguments in run time?
I think that yes ?
i get illegal state exceptions that passed values are null even though i havent added guard clauses
declaration: package: org.bukkit, class: Bukkit
thanks
You should watch a video about this on the internet. Annotation tutorial
ik how annotations work, but i thought jetbrains annotations are only for compile time (for IDE to mark yellow)
not for runtime
@EventHandler
public void onDamage(EntityDamageByEntityEvent e){
if (e.getEntity() instanceof Arrow){
Player player = e.getDamager();``` how do i get the item the arrow was fired with
arrow entities afaik doesnt hold that information. nvm
Thanks
How would an arrow take damage
how could i get the player speed in blocks per second?
so i could do something like if (getSpeed(player) > 2.25)
internally its a list iirc
you could cast it
or just new Arraylist(Bukkit.getOnlinePlayers())
Yea, however it might change at anytime so itâs a bit unsafe to assume so as an api user
Do what the javadocs tell you
then this
Because thereâs not particular order of the online players
But i would just use the api
Which the List interface to some extent promises
Wait wut..
what are you guys talking about?
Promises?
Yes, it the List interface promises that the implementation has some sense of order, for instance ::set and ::get which are index based.
Can you send PluginMessages with a player you got from the PlayerQuitEvent?
Ah ok you saying to use arraylist right?
If Bukkit would expose it as a list, then it would have to provide a list implementation which supports it, which it doesnât do as of now (It even goes against the collection interface by not supporting Collection::add)
in short terms yes
wdym exactly
And it shouldnât be that expensive if you use new ArrayList<>(blah);
(Altho a little but not noticeable)
Ahh.. sorry my bad for saying wrong here lol
No worries
i need to send some data when a player logs off the server to another server, can you use the player that left (PlayerQuitEvent#getPlayer) to send a plugin message?
I didn't mean literally to use List<>
Can some tell shortly about collection
On Mobile rn
i think yes, if you mean
player.sendMessage("")```
a plugin message channel
not a message
event.getPlayer().sendPluginMessage(Main.INSTANCE, "MyChannel", out.toByteArray());
you can try it out i guess
ye try and see
Bungee yea
?
can swear he is going to say use velocity
?
man thats not about you just read the message above those
oh
plugin channels don't just apply to bungee, for example you can use it for custom packets to communicate between a client mod and the server
yes i am aware
Hello how can I set the clicked item to Air in InventoryClickEvent? I have tried using the code below, but it doesnt work.
clickedItem.setType(Material.AIR);
set the slot to a new air itemstack
how to make the player climb like jumping on a slime at a certain height?
Isn't it possible to use remove item index?
I think:
item.setType(Material.AIR);
inventory.setItem(event.getSlot, item);```
shouldn't you do event.setItem(ItemStack)
Why are you pinging me
bekause i wanna say you that i am dumb
Ok you don't have to ping me for that
Still doesnt work
e.getInventory().setItem(e.getSlot(), null);
@waxen plinth
dsfgjklbjldsfjgjlsjdbfbgljlbjsdebhg
What are you trying to do
I can set the slot to everything else except air
Delete the item the player clicks on?
Yes
Ok
thats what i tried
^
declaration: package: org.bukkit.event.inventory, class: InventoryClickEvent
boo
e.setCancelled(true);
Bukkit.getScheduler().scheduleSyncDelayedTask(() -> {
e.getInventory().setItem(e.getSlot(), null);
});```
grosssssss
You often need to delay stuff by a tick for inventory events
that's so annoying
I know
You could also just do a scheduler.runTask()
Ok and you could also not ping me
Sure my bad
Seriously I have been pinged 4 times in the last 5 minutes here
that's an uneven amount
new rekort
Did you really just complain about pings lol
Replies just give some context for me, so I'm used to using em
Disable them and don't be a baby.
you can reply w/o pinging
Oh can you :o
Yeah, the @ symbol on the right side.
Or people could just not ping me unnecessarily
I'm open to being pinged when it makes sense
That's what happens when you're in a conversation.
If it was random, sure, if you're actively talking to people, don't complain.
That's the point of them.
If you don't like pings, disable them.
I generally don't complain about reply pings
I complain more when people ping me outright when they really don't need to
Lol alright
Sorry that my preferences upset you
Do you have ideas what an reforge effect for an bow with the reforge spiritual can have?
Just don't like when people complain about stupid shit that they can prevent. ÂŻ_(ă)_/ÂŻ
ÂŻ_(ă)_/ÂŻ
What does that mean
"don't like junk mail? just delete your email account!"
Ah yes, because everyone can prevent junk mail. LOL
getting a bit off topic eh
Still doesnt work
I made an plugin where you can reforge stuff with souls and you can reforge an bow to spiritual, but idk what the special effect of the bow could be
Oh
public void deleteUnwantedItems(InventoryClickEvent e) {
if (e.getClickedInventory() == null) {
return;
}
if (e.getInventory().getHolder() instanceof BodySearchGUI) {
return;
}
e.setCancelled(true);
new BukkitRunnable() {
@Override
public void run() {
e.getInventory().setItem(e.getSlot(), null);
}
}.runTaskLater(Main.instance, 1L);
}```
Idk the context, but maybe you can get more souls with it or something
Doesnt set it to air
Why do people still use BukkitRunnable
Add some debug output to make sure the code is actually running
Wait, it might have to be e.getClickedInventory().setItem
^
So the event is being cancelled?
I wonder if setting the cursor item to null would work without the delay?
đ€
.
..what
Now it works lmao
set their velocity?
Cool
how
e.getPlayer().setVelocity(new Vector(0,3,0));
?
no, that you will get through a soulsheep which drops soul fragments which upgrades you souldropchance

A little previev
You could still have some sort of drop multiplier for that
youtube.com sir
a 50kb mkv file? lmao
don't use any undefined symbols
im not?
where?
in line 37
did you copy any code?
no
show the correct file please
the one thats mentioned in the error
idk which one it is because it's not visible on your screenshot
scroll up when you hover over the "cannot find symbol" section
might give you more info
there ya go
invitecommand class, line 25 etc
I would try Invalidating your caches and restarting
i did
i upload an video on yt rn then i can show you what i have done
multiple times i even reinstalled java and intelijj
scroll up and show the file again
maybe try duplicating the project?
how?
?paste the invitecommand class here pls
there is literally nothing wrong with it theres no point
okay then good luck getting it to work
its a bug with intelijj i just dont know how to fix it
yeah already went over all of those articles, nothings working
is your project on git?
just trying to see if you're able to replicate the issue
https://youtu.be/2PKY_JnGqtk here is my little soul plugin who ever is interrestet
How the hell am I suppose to use this instead of using bungee api https://github.com/redis/jedis
doesn't bungee use redis
idk
bungee does not use redis lol
for example, i would like to set the light leve to 13 in that glasses area
the more you know
im trying to use it so I can send messages across servers
help, text isn't above spawner
you could use the light block that 1.18 has
i said 1.16.5
if you don't want to do that, you might have to use Packets / NMS
sure, redisson is a nice java library of interacting with redis
redisson?
The text is not directly on top of the spawner, how to fix?
HologramBuilder hologram = new HologramBuilder(plugin);
hologram.create(b.getLocation().add(0,1,0), "Teste");
private KSpawners plugin;
private List<ArmorStand> holograms = new ArrayList<ArmorStand>();
public HologramBuilder(KSpawners plugin) {
this.plugin = plugin;
}
public void create(Location l, String text) {
ArmorStand as = (ArmorStand) l.getWorld().spawnEntity(l, EntityType.ARMOR_STAND);
as.setVisible(false);
as.setCustomNameVisible(true);
as.setCanPickupItems(true);
as.setGravity(false);
as.setSmall(true);
as.setCustomName(PlaceholderAPI.setPlaceholders(null, text.replace("&", "§")));
holograms.add(as);
}```
so if other people were gonna use this plugin would they need to have a redis db?
yes
okay
Block locations are not centered
They are in the corner
im assuming i can just install redis on a vps
how to fix
Doing add(.5, 1.5, .5) instead of add(0, 1, 0) should work
yes you can, pretty easy too
trying
it's too high
in 1.0
,_,
yeah im confused on how its suppose to work
Ok then use common sense
Just add less to the y
ok;-;
Yeah exactly
We're not here to write all your code for you, think for yourself a bit
How could I do a custom wait time?
solution = 0
alt = 1
ctrl = 1
delete = 1
if solution == 0 then
print(solution + alt + ctrl + delete)
end```
Lua
You can easily google these things
I did but everything coming up was like confusing confusing
question, is there a better way to check if a server is the same as another server than to just check the name?
bro even i understand that
What?
and i don't use lua
require "socket"
function sleep(sec)
socket.select(nil, nil, sec)
end
sleep(0.2)
Nah it was another website
That doesn't explain anything
what's a pub and a sub?
a client can subscribe (listen) to a topic
another client an publish to a topic
so basically message brokering
i was told to use gradle or maven instead of the 1.18 spigot jar for plugins but im not sure where to start. could someone help me get started?
yes ill help you
so im assuming I will need those
its pretty easy, in your pom.xml add this:
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.18.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
```And if you are using intellij, on the top right of the file there will be a reload button, press that and you're done
oh i dont even have gradle installed
are you using intelij?
eclipse
oh then iirc you need the maven plugin and then you can make maven projects
oh
i used to use eclipse for a few years tho i switched to intellij
should i swap to intellij
its just better
okay yeah im gonna need your help implementing this
thats fine with me
oh and if you have intellij there is a plugin named "Minecraft Development" or smt like that, it can autosetup plugins for bukkit, spigot, paper, bungeecord, waterfall and fabric/forge mod and some other things
just read their docs lol
do you know of a tutorial for intellij i could only find one for eclipse which is why i used eclipse
I've got the connection down
This is #help-development
Ask somewhere else, this is a chat for people to get help with code
uh so im connecting to redis right and now my plugin is just not loading when I call the instance of i t
no errors or anything its like it froze
what do I do here?
Are you trying to add a dependency?
Im making NPCs, but i have an issue. When i use the code below to display the NPC, everything works fine, and the NPC has a skin and everything.
connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, npc));
connection.send(new ClientboundAddPlayerPacket(npc));
// connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER, npc));
But when I uncomment the third line, the NPC gets the default alex/steve skin. There are no errors in console.
connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, npc));
connection.send(new ClientboundAddPlayerPacket(npc));
connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER, npc));
btw the third line is to remove the npc's name from tablist
@crisp arch that's because player info contains the skin and other profile properties
The most reliable solution is to simply also add a custom tab system which will fill the tab with blank entries and push the npc names off the end.
the unreliable solution is to wait several ticks and then send PPOPI remove
However some of the time the skin will still go away since there is no real way of knowing how quickly the client will receive the second packet
There is one slightly more complicated but also somewhat more reliable way
so wait, how do plugins like Citizens do it?
which is why you start be sending PPOTransaction
and then await for the response from the client
and then you send the removal since that means at least 1 tick will have gone by first... but ofc the name will flicker in tab list this way no matter whatever.
I think Citizens uses actual entities, not packets.
^ that is highly recommended no matter what
Hey I swapped out the 1.17.1 jar I was referencing for plugins for a newly built 1.18.1 jar and now all my references can't be resolved (import doesn't recognize anything from org.bukkit etc). I unzipped the jars and noticed that the 1.18.1 jar I built only has four classes in it, which doesn't seem right. Are we supposed to import something else now?
the entity tracker takes away a lot of the hard work
I took a look at the release thread and it just said "we don't expect many plugin breakages except for anything touching biomes or generation" so I'm pretty confused about this
but even if you use tracked entities you still need to handle player info yourself... and I do not think there is any way around them flickering
Did you get the jar through BuildTools?
Yes I did
pause```
Did it actually finish successfully?
It was a tight-knit bunch
yeah
These days I'm still working on the same library I used back then
I compiled my plugin with intellij went to the location and there's no .jar file
Some things never change I suppose
@waxen plinth which one was that?
RedLib
link
Hmm, Iâd try redownloading the latest BuildTools and run that again. Run it in a new directory too, that way it can start fresh.
I mean TBH I still work on my engine although it's very different
Copying spigot-1.18.1-R0.1-SNAPSHOT-bootstrap.jar to E:\Users\_____\Games\Minecraft\SpigotBuildtools\.\spigot-1.18.1.jar
- Saved as .\spigot-1.18.1.jar```
Read the release notes
What engine?
Where to find .jar file after compile?
I remember your Tr.y thing, did you ever make anything of it?
inb4 "that's vavr now"
lol no, that was bad stuff.
Was funny though
It should normally be in the target directory. Which is located in your projectâs main directory.
It was a fresh update of BuildTools, I had to update it. Had to update Java too apparently, so that's also a fresh install.
yeah it was, these days I use kotlin primarily it's more powerful.
I checked but nope
đ
I'm working on a custom server impl that's not just nms copy pasted into another language.
Read the release notes
Your question is clearly covered there and probably 100 threads made since
yes, since I have my networking library and my engines architecture in kotlin.
Makes sense
uhm ```
[16:41:15 WARN]: redis.clients.jedis.exceptions.JedisDataException: ERR Can't execute 'publish': only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT / RESET are allowed in this context
[16:41:15 WARN]: at redis.clients.jedis.Protocol.processError(Protocol.java:96)
[16:41:15 WARN]: at redis.clients.jedis.Protocol.process(Protocol.java:137)
[16:41:15 WARN]: at redis.clients.jedis.Protocol.read(Protocol.java:192)
[16:41:15 WARN]: at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:316)
[16:41:15 WARN]: at redis.clients.jedis.Connection.getUnflushedObjectMultiBulkReply(Connection.java:282)
[16:41:15 WARN]: at redis.clients.jedis.JedisPubSub.process(JedisPubSub.java:131)
[16:41:15 WARN]: at redis.clients.jedis.JedisPubSub.proceed(JedisPubSub.java:124)
[16:41:15 WARN]: at redis.clients.jedis.Jedis.subscribe(Jedis.java:7335)
[16:41:15 WARN]: at dev.stuntcore.database.RedisManager.lambda$new$0(RedisManager.java:24)
[16:41:15 WARN]: at java.lang.Thread.run(Unknown Source)
I've been moving away from minecraft, though I still write a lot of code for it
Trying to learn rust and have also just been writing pure java libraries
Okay people have said that before but the 1.18.1 release notes just say plugins won't brea unless they touch biomes/particles.
https://www.spigotmc.org/threads/9-years-of-spigotmc-spigot-bungeecord-1-18-1-18-1-release.534760/
Bootstrap Jar
The main spigot-1.18.jar is now a bootstrap jar which contains all libraries. You cannot directly depend on this jar. You should depend on Spigot/Spigot-API/target/spigot-api-1.18-R0.1-SNAPSHOT-shaded.jar, or use a dependency manager such as Maven or Gradle to handle this automatically.
Copy pasted directly from your link
thought you liked kotlin
Oh it's on a second comment fml
@waxen plinth yeah I mean until recently MC was just on the side... but I don't like working 9 to 5. I do crypto stuff and I'm writing this custom server for a network so it's pays well enough to be worth it.
Nice
I would rather work a 9 to 5 because I like stability more than anything
But I can understand the disdain for it
Kotlin has plenty of problems... but I was just running into the edge of what was possible in java. Improving design further meant taking performance hits
Now I've run into the edge of Kotlin and I'm contemplating scala.
The edge being what?
Java has always been very accommodating of my abstractions
Though seeing as I used to call your code "lambda porn" it makes sense that you would go towards a functional lang
how can I remove commands from the knownCommands Map?
do i need to get it with reflections
im trying to invert the entity facing direction with the Entity#movementTick from nms entity but it is working for only 1 direction (west). This is my current code: https://paste.md-5.net/wohoyexili.java (dont care the flying slime on the final of the video đ€Ą )
This is a method that does exactly that
You can copy-paste it if you want
GEN 3 (Vespa based engines):
public class ExampleComponent implements Component {
private final Togglable addListener, removeListener;
public ExampleComponent(final Holder<Player> players) {
addListener = players.onAdded(player -> {
System.out.printf("%s was added!", player.getName());
});
removeListener = players.onAdded(player -> {
System.out.printf("%s was added!", player.getName());
});
}
@Override public void onEnable() {
addListener.enable();
removeListener.enable();
}
@Override public void onDisable() {
addListener.disable();
removeListener.disable();
}
}
GEN 4 & 5 (Wespen based engines):
public class ExampleComponent extends Component {
public ExampleComponent(final Holder<Player> players) {
addChild(players.onAdded(player -> {
System.out.printf("%s was added!", player.getName());
}));
addChild(players.onRemoved(player -> {
System.out.printf("%s was removed!", player.getName());
}));
}
}
GEN 6(Suzuebachi based engines):
inline fun Toggled.Example(players: Holder<Player>) {
players.onAdded { println("$name was added!") }
players.onRemoved { println("$name was removed!") }
}
Gen 3: 21 lines -- 120 bytes
Gen 4 & 5: 10 lines -- 456 bytes
Gen 6: 4 lines -- 80 bytes
how are they stored exactly? what is the string? only the command name or plugin:commandname?
Command is pretty straightforward
Hmm
So you're trying to reduce the boilerplate as much as possible
Yes but also reduce the overhead
thre is almost no overhead from the kotlin example by comparison
Kind of reminds me of my enchant library
addTrigger(EnchantTrigger.MINE_BLOCK, (e, l) -> {
e.getPlayer().sendMessage("You mined a block!");
});```
Though there is some value in boilerplate like classes and overridden methods
yeah well sort of, I just believe Java got everything you need
oh i did something similar for my enchants, tho it's a bit bigger
you implement an interface
and you need to implement various methods to get the max level, type, rarity
im using different jedis clients for publishing and sub
the most direct java translation is this:
static void Example(Toggled scope, Mutated<Player, Player> players) {
scope.invoke(scope, Containers.getOnAdded(players), player -> {
System.out.printf("%s was added!", player.getName());
});
scope.invoke(scope, Containers.getOnRemoved(players), player -> {
System.out.printf("%s was removed!", player.getName());
});
}
and then a final one to execute code for the enchant effect
I do focus on abstractions like that a lot, but the rest of my work usually involves pushing performance to the limits
apart from your sanity
đ
Help with inverting entity direction
bump
Both
Does spigot in 1.18 require a plugin.yml in independent libraries now?
The direct command name, alias, and fallback prefixes are all used
A plugin that depends on a unrelated library fails to load because spigot attempts to initialize the lib jar as a plugin
And as a independent lib, it lacks one
I suppose we should move to DMs
I donât think so. A library is a library and you can just access it through your plugin.
so let's say my command is called test and has test1 as alias, i need to remove
test, pluginname:test, test1, pluginname:test1
there is no plugin.yml
How do you deal with scopes there?
It attempts to initialize the jar as a plugin, fails, and does not add it to the classpath
what unregisters that?
Yes, because it is not a plugin
then why do you put it in the plugins folder?
Because it is a library another plugin depends on
public class HelloEnchant extends CustomEnchant {
public HelloEnchant() {
super("Hello", 1);
addTrigger(EnchantTrigger.MINE_BLOCK, (e, l) -> {
e.getPlayer().sendMessage("Hello");
});
}
}```
you should shade the lib into your plugin
it's worked fine before
Spigot now has a separate libraries folder I believe
Well, you can create libraries that have a plugin.yml, but that means that you would also have to have a class that extends JavaPlugin.
Itâs likely that whoever created that plugin either forgot to add a plugin.yml or didnât realize that they didnât need to extend JavaPlugin.
That... is not the issue
Am I misunderstanding?
you can't have libs in the plugin folder, everything there must provide a plugin.yml and a main class extending JavaPlugin
how does enchant access players and what not?
else spigot doesn't know what to do with it
So it's something 1.18 introduced then
and throws an exception
Is that change documented somewhere?
You call addTrigger, which takes an EnchantTrigger<T extends Event>
afaik it's always been like that
That is not true
Yes it is
Then you supply a lambda which takes T and an int for the level
if you had used a different lib, it might have had a plugin.yml
plugin lib
Then I am suprised how it worked until 1.17
and a class extending JavaPlugin
Everything in the plugins folder needs a plugin.yml
It's to make it easier to define custom enchantments, that lambda will only be run if they mine a block with a pickaxe enchanted with your custom enchant
bump
thanks
Otherwise you would need to iterate over all the commands when running one to see which one matches
So you're telling me the fact that it has worked until now was because of a bitflip caused by a solar flair, and the only way to load external libraries now is to shade them?
is that the exact string? "pluginname:commandname"
Yes
Is there a changelog somewhere for major API changes? I'm not interested in poring through the commit history on Stash
You can try these things yourself
it's always been like that
tyty
Then please tell me how I was able to load libraries by placing them next to it until now
another plugin probably shaded them in
as i said, the lib probably had a main class and a plugin.yml
It did not
that or the lib was a plugin, yeah
a big part of what my engine focuses on making reactive code that stays clean... so this code here doesn't translate to very readable java... because there are many layers of Toggled that you do not see at all.
fun Toggled.whatever(online: Adepts) {
val playing = MutableTable<Id, Togglable>()
(online - playing).onEach { id, adept ->
adept.handle("/spec") {
val target = player(online and playing, "That player is not online and in a game.")
action {
playing[id] = playing[target.id]
channel.send("§7You are now spectating §c${target.name}§7.")
}
}
}
}
/spec command is only listening to players who are not playing a game... and the only valid targets are people who are playing a game.
if you were putting it into the plugins folder
I made both the plugin, and the lib
@regal dew okay so I think I got it setup properly how can I tell if I did it properly? Is the only way to see if it can communicate between servers?
abstracting away significant portions of program logic is fine if you don't need the lower levels
e.g. python
sounds pretty strange to me but even if it worked it should not be like that
yeah that's not how your libraries should be set up
either shade it or make the lib a plugin
^
Yeah that seems reasonable
please dont @, im not a cs course xd
Anything for the abstractions
so I've been all about separating the enchantment (the data aspect) and the logic
ah sorry
Data such as what?
abstraction đ
just test it, send some data and retrieve it
me out here basically writing Spring Boot for Spigot
that's what I did and seems like it works
well IDK enchantment name etc, what if bound to the player... obv it's tricker when you are working within the confines of spigot and nms.
I see
annotation magic: the plugin
My command handler separates data and logic to the maximum degree
So much so that it has its own markup language for commands
commandname int:arg1 {
hook hookname
permission test.thing
user player
help This is an example
}```
@CommandHook("hookname")
public void example(Player sender, int arg1) {
// Do stuff
}```
i just let people annotate the full command including parents and the command handler throws together a command tree at runtime
i love touching stuff i should not touch in spigot, it makes me understand how shit works
anyone know the MojangMappings equivalent of DataWatcher#watch ?
I once reflectively modified the order in which events fire LOL
lmao
what was the outcome?
No that's so much more verbose
It really messed some shit up with other plugins
That's how almost every other command library does it
But it's so elegant with this format
how to set skin in a skull on itemstack?
idk i think requiring a markup language is pretty bleh
basecommand,alias {
// metadata here
childcommand {
}
}```
dude imagine putting that code inside a plugin and making it only work after 10 restarts or so
lmfaoooo
but like I would probably end up with something like:
interface Enchantment {
name, blah blah
}
//ok so just a normal class here.
fun Enchantment(name, blah blah) = object : Enchantment {
}
val Players.Enchantment get() Toggled.(name, blah, blah, (Player, ...) -> (Unit)) -> (Enchantment) = { name, blah, blah, onUse ->
val enchantment = Enchantment(name, blah, blah)
onEach { _, player -> {
player.onUse { onUse(player) }
}
enchantment
}
from player
It's really nice especially because it has an intellij plugin for syntax highlighting
doing @Command("egg") and just letting the command handler throw everything together at runtime is more fun
or texture/signature
Yeah that'd be messy
You could always create your own triggers to simplify it though
also frankly I'm sick of adding in other language files/etc., I do enough of that with JavaFX
so in your <scope that uses enchantment>
val customEnchantment = players.Enchantment("hello", ..., onUse = {
//impl
})
Nah this is cooler
which bounds the enchantment into the scope with the players who it will be applicable to
oh yours lets you do parenting that way, that's actually pretty good
i misunderstood, mb
in case you wanna see, this is how I manage enchantments:
public class Efficiency implements RareEnchant, MiningEnchant {
@Override
public String getId() {
return "efficiency";
}
@Override
public String getDisplayName() {
return "Efficiency";
}
@Override
public String getDescription() {
return "Increases mining speed.";
}
@Override
public int getMaxLevel() {
return 6;
}
@Override
public int getMaxFindable() {
return 5;
}
@Override
public EnchantRarity getRarity() {
return EnchantRarity.SIMPLE;
}
@Override
public EnchantType getType() {
return EnchantType.PICKAXE;
}
@Override
public void onMineTick(MiningWrapper wrapper, int level){
double multi = 1 + level * 0.06;
if(level == getMaxLevel()) multi += 0.04;
wrapper.setDamage((int) (wrapper.getDamage() * multi));
}
@Override
public void onMineBlock(MiningWrapper wrapper, int level) {
}
}
Jesus
sorry lol
Yeah that's why we need abstractions
I think it's just set no?
the syntax is still a bit questionable, but the parenting is nice
With mine the trigger you specify determines the default items it applies you
wdym?
You simply pass the name and max level in the constructor rather than needing 2 methods for them
the main reason I don't want to do something like that on my end is because a lot of what I write focuses on modularity
referring to Redempt's library
ah
Why is it questionable?
hard to add modular parenting cross-plugin through a syntax file
I agree with this
because I see asterisk and think "why is there a pointer here"
Oh lol
btw if you wonder why i have on mine tick and on mine block it's because of custom mining, i can tweak all values i want
the way I do commands now is completely functional... no concept of sub commands.
Yeah it does take some getting used to but it cuts through boilerplate
i spent this semester writing low-level C that's basically a step above ASM
How's that work?
the only reason I have subcommands at all is solely for organizational purposes for the player
well for starters you can just do like:
players.onEach { _, player ->
player.handle("/parent sub") {
}
}
but from a programming standpoint, it's functional
like, the subcommand system is entirely just for "help [command]"
Well then what happens when you have a parent command that takes a string argument
varargs
And a player wants to run that base command with the argument sub?
but you can also do:
players.onEach { _, player ->
player.handle("/parent") {
matching("sub") {
}
}
}
this syntax looks kinda illegal lol
That's not really separating metadata from logic though
kothlin right
Yeah
the tl;dr on why I'm just going to keep using annotations is because I want people to be able to develop plugin extensions
fixed, player
aight
and matching is just a type adapter like any other so you could also have:
players.onEach { _, player ->
player.handle("/parent") {
player(moderators) { target ->
//if they targeted a moderator
}
}
}
the rpg plugin i'm working on is designed with modules in mind
In mine that would look like
so like it'll load behaviors/commands/abilities from other .jar files
parent player<moderator>:target {
}```
And then the command would just take a Player as an argument
plus the entire thing is customizable so working with it is absolute hell because nothing is hardcoded besides the core systems, it's all config
is it?
i hate coding it
yeah but that's complexity and how do you define who mods are etc?
kick it back
You would define a constraint for the player type
That's up to you
i tried passing in an int and a byte but it doesnt match the method's parameters
You can define constraints for anything
where do you add that though? I don't see where you gain value from having a markup
Error '-'
it also means now your commands have depends all the way down to the file system
It's reusable
Caused by: java.lang.ClassCastException: org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaItem cannot be cast to org.bukkit.inventory.meta.SkullMeta
It's not a skull
Well the resource is shaded into the jar
send the decompiled code ill check RQ
I don't really see how it's all that different from depending on another class
So the PlayerQuitEvent only triggers when a player leaves the proxy, and not switches server, is there any other event that i can use for listening when a player switches server (on a spigot plugin)?
And there is plenty of value in defining constraints like that
decompiled code?
code:
public void createHead(Location l, String Nick) {
ItemStack skull = new ItemStack(Material.SKULL);
SkullMeta skullMeta = (SkullMeta) skull.getItemMeta();
skullMeta.setOwner(Nick);
skull.setItemMeta(skullMeta);
ArmorStand as = (ArmorStand) l.getWorld().spawnEntity(l, EntityType.ARMOR_STAND);
as.setVisible(false);
as.setCustomNameVisible(true);
as.setCanPickupItems(true);
as.setGravity(false);
as.setSmall(true);
as.setHelmet(skull);
holograms.add(as);
}
public void unregisterCommand(Plugin plugin, CommandExecutor executor){
knownCommands.remove(plugin.getName() + ":" + executor.getName());
knownCommands.remove(executor.getName());
for (String alias : executor.getAliases()) {
knownCommands.remove(plugin.getName() + ":" + alias);
knownCommands.remove(alias);
}
}
so would something like this work?
show me where you add the constraint though
it is called when the player switches server
You can do int<1,100>:number and it will only allow ints from 1 to 100
commandexecutor is my class extending Command
no i mean on a spigot plugin
yes
a plugin not on the proxy
yes
i don't see it
players.onEach { _, player ->
player.handle("/parent") {
val whatever = int(1..100, "error when out of bounds")
}
}
then you coded it wrong
oo i need to add that
nice idea
But int is something you created
idk, i can't read your mind
My default int type also can be constrained by default
But when you want to define another type?
Like if you have a team, and you want to constrain it so only a team the player owns can be targeted?
When a player switches a server within the proxy, can you know when that happens from a server in the proxy's point of view?
You register it prior to parsing the command file
int is not since it's compile time checked
@rigid drum i think it might be SynchedEntityData#define, but im not 100% sure
How is it a magic value
@waxen plinth and where do you register it?
the proxy knows which player is where at all times, the server does not know about the proxy at all without complicated messaging across the plugin message channel
Help?
public void createHead(Location l, String Nick) {
ItemStack skull = new ItemStack(Material.SKULL);
SkullMeta skullMeta = (SkullMeta) skull.getItemMeta();
skullMeta.setOwner(Nick);
skull.setItemMeta(skullMeta);
ArmorStand as = (ArmorStand) l.getWorld().spawnEntity(l, EntityType.ARMOR_STAND);
as.setVisible(false);
as.setCustomNameVisible(true);
as.setCanPickupItems(true);
as.setGravity(false);
as.setSmall(true);
as.setHelmet(skull);
holograms.add(as);
}
You register it in your onEnable typically
like what if I want to constraint to people in a game...
okay, thank you
is this it?
fun Toggled.whatever(online: Adepts) {
val playing = MutableTable<Id, Togglable>()
(online - playing).onEach { id, adept ->
adept.handle("/spec") {
val target = player(online and playing, "That player is not online and in a game.")
action {
playing[id] = playing[target.id]
channel.send("§7You are now spectating §c${target.name}§7.")
}
}
}
}
Caused by: java.lang.ClassCastException: org.bukkit.craftbukkit.v1_8_R3.inventory.CraftMetaItem cannot be cast to org.bukkit.inventory.meta.SkullMeta
Your item is not a skull
in this example the only place that contains the information about playing is in this method itself.
so I cannot register it way ahead of time
certainly not in an onEnable
i need to make this:
1.18.1
a skull in 1.8
is a skeleton skull
java.lang.NoSuchMethodError: 'net.minecraft.nbt.NBTTagCompound net.minecraft.world.item.ItemStack.save(net.minecraft.nbt.NBTTagCompound)'
You definitely could define that in the onEnable
you need to add damage
no import issues
3 iirc
The constraint method takes a lambda which returns a predicate, essentially
@waxen plinth certainly not
how to set player skull?
that's why too far up the chain
you would end up dragging that information way out of scope
You could return a predicate which checks that the given player is online and in a game
val player = Adapter1<Channel, Mutated<*, out Channel>> { channels ->
string(this).mapNotNull { start -> channels.values.filter { it.name.startsWith(start, ignoreCase = true) }() }
}
is ow new ones are defined.
yes
the channel stuff is from my server it's effectively lower level player
Well in that sense there's nothing stopping you from just having a helper method that tests a condition
can anyone help me with this? https://wiki.vg/Entity_metadata#Entity_Metadata_Format
im trying to make my NPC crouch, and im trying to use the SynchedEntityData but i cant seem to figure it out
Constraints are not meant to be that context-specific
@waxen plinth but why not? I don't lose anything making mine context specific.
Less separation of metadata from functionality
The command file lays out the command, its subcommands and arguments and other pieces of data
Not really
Do you mean you want to check if the player sending the command is in the same game as the player they're targeting or something?
Also commands are rarely not part of the hardcoded section of whatever you are writing.
re send code
@waxen plinth sure might be one case
bump
protocollib?
If you have a game manager or similar, it would definitely be possible to define a constraint which checks the game manager to make sure the players are in the same game
just mojang mappings
so you wanna make the npc sneak?
public void createHead(Location l, String Nick) {
ItemStack skull = new ItemStack(Material.SKULL, 1, (short) 3);
SkullMeta skullMeta = (SkullMeta) skull.getItemMeta();
skullMeta.setOwner(Nick);
skull.setItemMeta(skullMeta);
ArmorStand as = (ArmorStand) l.getWorld().spawnEntity(l, EntityType.ARMOR_STAND);
as.setVisible(false);
as.setCustomNameVisible(false);
as.setCanPickupItems(false);
as.setGravity(false);
as.setSmall(true);
as.setHelmet(skull);
holograms.add(as);
}```
so for me that would look like:
fun Toggled.Game(players: Adepts) {
players.onEach { _, adept ->
adept.handle("/whatever") {
val target = player(players, "That player is not in game or online")
action { /*whatever*/ }
}
}
}
yes, according to wiki, i just need to send (0, 0b2) to make the NPC sneak
error?
but idk how to do that
@waxen plinth game manager like things I've moved far away from as well, since they normally break DIP
2 sec
I see
i've spawned in the NPC and everything, i just need to send an extra ClientboundSetEntityDataPacket packet
check if the nms class you constructed has a method to make the entity sneak
and then you can send a packet to update it
@waxen plinth TBH I used to mostly agree with your way... because you need to deal with tab completion anyway
not sure if the sneaking state of a player is in metadata
EntityPlayer.setSneaking(boolean); ?
but I figured out how to handle tab complete functionally so now I don't see much of a reason for the extra complexity... Especially since I'm not a fan of like automatic /help registration and stuff. I think it's generally very bad.
yea just checked there is
You don't like automatic help menu generation?
yeah quite poor IMO
How would you do it?
apparently it's in metadata
I find automatic help menu generation wonderful, it saves me a lot of work
I just don't, I mean if that's really something that's required then ok I build I a system that wraps handle
im checking rn, but doesnt seem like it
It's boilerplate that can easily be abstracted away and standardized
So why not standardize?
But most of the time... you can just write a command that spits out a page of docs
ill look up mappings for EntityPlayer#setSneaking
Having it be generated also makes it really easy to make it configurable
and for many commands you really don't need or want help
plus it has the added issue of displaying commands that are not for the person using /help
It doesn't
and there is no way around that without breaking a lot of design principles
Mine will only show them commands and subcommands they have permission to run