#help-development
1 messages · Page 2243 of 1
ofc
k
the last parameter in any function can be a vararg (Java)
@noble lantern plss
If none of those options work, then HorseAPI seems to just be broken asf and you may need reflections
or
nope, instantly adult
Interact event
-> Cancel it
-> add health manually
-> remove 1 from players in hand item
-> and play breed particles (if applicable for that item)
Thats probably easiest way now since all that shiz doesnt want to work
damn
sorry himme a sec
ugh
this
okay wait
i looked at the NBT data of a freshly spawned baby horse
i found this
lemme try that
yeah thats what i was looking at
doing /summon with a negative age value summons a baby horse
-1 didn't work though
maybe it has to be a specific negative value?
the horse is age locked right?
yes
yeah idk why that wouldn't work
age lock doesnt work for hand feeding though
Player chat event isn't cancelled for the entire server spigot, so others plug-in can use the same one everytime. Help?
cancelling a chat packet still passes it to other plugins
uhh pretty sure cancelling packets doesn't
meaning logging plugins will still log it, etc
ah wait
I'm stupid
yes if you cancel the incoming packet
why was I thinking of outgoing
kek
I mean.. what's the goal
we need more info to tell you what's best
using the API is probably the best minus a few circumstances
the API lol
unless the goal is to prevent any part of the server from even knowing that a player chatted, then use the API
otherwise, the only way is to add a handler into the netty pipeline & don't let it pass
as a wise man once said: if it exists in the api, you should use it.
Unless the API is trash, the lessr wise man said
just ignore the API & write directly into NMS 😏
That's exactly what I do lmao
I can't bother doing 20 jumps through the API if I can just call a specific field
what
I'm talking about cloning NMS source into your IDE & coding onto it instead of using spigot
Ahhhhhhh
not using reflection to call a method or get a field
That colors fine imo
Huh thats actually cool asf
Okay you should make a mobile app for it for shits and giggles
today it was my first day i've used yield in switch expressions
java 16
but I forgor
omg thats badass
earlier today i did some stupid code as a joke
and its actually a real thing
LMAO
lemme find it
return switch(type) {
case TYPE.FOO -> {
if (this and not that) {
yield true;
}
yield false;
}
}
ofc with more cases and more complicated checks
hell no
that works no? what do you want to change
tfw you swap to maven to not have to deal with shadowjar, and now your maven refuses to import mongodb
I was meming in general earlier just posting code that looks weird and wouldnt work xD
Hence why i was suprised when i saw yield, cause i was like oh they actually have that haha
Hey could anyone help me? I want to write a plugin for a leveling system for each player. Player will have different skills which each will have a level. How would I store this data? I was thinking reading and writing to a json file which will work and saving it every five minutes and keeping the Arraylist with playerlevel objects in memory. But won't this eventually take up too much resources since this object will become so large?
IO should be done async so it doesnt really matter if you need 0.5ms or 5ms to read/write files.
Files are decent if you only need the data to exist on one server. It it needs to be shared between several
instances then you need to use a Database.
There is a general approach to data lifecycles. Let me explain a bit more.
have you heard ternary operator
Yes but i didnt use it just to make people more mad
String string = that == this ? "this" : "that";
oh
you've just earned another hater then
i love ternary operator
Hate it
xD
That shit makes dyslexic people shiver in theyre boots
im trying to figure out wether b is d or if d is b and you over here like ?? :: ;; ?? ::
xD
Sometimes it’s more comfortable to use it because that could shorten the code a bit
- Data exists in 2 states: Live and persisted. Or in other terms: In memory or on disk.
- Data has scopes. Usually you would differentiate between application scope and session scope.
This defines when data should be loaded from disk into memory.
Application scoped data is loaded when the application starts and saved when the application stops.
Session scoped data is loaded when a session starts and saved when a session stops.
Now we just need to define a "session" in minecraft terms:
A session of a player usually starts when he connects to the server and stops when he quits.
The same goes for chunks for example. A chunks session starts when the chunk is loaded and stops when the chunk is unloaded again.
Let me explain how to approach player sessions....
boolean hah = otherTernary == true ? anotherTernary : null;
This is interesting, thanks for explaining 🙂 I'm listening 🙂
Data handling is a lot like baton running ngl
Hand baton to one person, baton is held by him for a bit, and eventually it comes back around
xD
Hm since you're talk abt data, what should I do if a player is online on one server and an admin tries to modify something about said player from another server?
Like whwre inventories are synced across a group of servers like skyblock
I typically:
Project startup:
-
Keep data and only edit the cached values for said player (Typically you have a HashMap<UUID, PlayerDataClass>) inside of a DataManager class that handles all this loading/saving
-
Have singleton timer that runs async every x minutes, where it loops through the values of that map, and writes them to file (use the async bukkit timer)
Player join:
-
Load data on async player join event, make sure to execute a blocking get no async or else the player logs in before data is loaded (This is the only non-async operation you should do, is the GET in an async player join)
-
On player disconnect, write they're cache to file and remove from cache, repeat
Basically what smile was saying but simpled down to minecraft terms
This is just something basic, you can get more complex the more requirements you need, like with smile said when you need data synced between servers, or servers need to share data
Problem i had with loading on async join is of players switch servers, it starts loading their daya before it saves on the prev server
Shouldnt really be an issue imo
just throw his data away it he switches servers
its no longer needed, hes not there and he didnt do anything to effect his data if he just instantly switched
Besides the player cant leav in async player join anyways
the cancel button isnt there, so youll have to alt f4, or modded clients
Theres a bunch of Statistic issues for spigot ide just handle them myself at this point ngl
Like BREAK_BLOCk statistic not working if the item doesnt drop an item (BlockBreakEvent#setDropsItems(false))
Yep
If you setDropsItems false on BlockBreakEvent the BREAK_BLOCK statistic breaks and wont increase
I reported it on spigot, doc opened a PR but no new news on it yet
ohhh i see
So?
This shouldnt be an issue either
First we need to define our data class.
@Data
public class PlayerData {
private long firstLogin;
private ClanUserData clanUserData;
private JobData jobData;
}
@Data just generates getter, setter, toString, equals and hashCode methods.
Next we define an Interface which has the task to save/load this data. The implementation can be done with Files or whatever.
public interface PlayerPersistenceHandler {
CompletableFuture<PlayerData> loadDataAsync(UUID playerId);
void saveDataAsync(UUID playerId, PlayerData playerData);
}
Dont be scared by the CompletableFuture. You can simplify this if you want.
Next we define our manager class that holds the live player data. This is our single entry point for interacting with player data.
@RequiredArgsConstructor
public class PlayerDataManager {
private final Map<UUID, PlayerData> playerDataMap = new HashMap<>();
private final PlayerPersistenceHandler playerPersistenceHandler;
public void loadPlayerData(UUID playerId) {
PlayerData loadedData = playerPersistenceHandler.loadDataAsync(playerId).join();
playerDataMap.put(playerId, loadedData);
}
public void unloadPlayerData(UUID playerId) {
PlayerData liveData = playerDataMap.remove(playerId);
if(liveData == null) {
return;
}
playerPersistenceHandler.saveDataAsync(playerId, liveData);
}
public PlayerData getPlayerData(UUID playerId) {
return playerDataMap.get(playerId);
}
}
At last we are defining our listener. This couples the data with a players session:
@RequiredArgsConstructor
public class PlayerDataListener implements Listener {
private final PlayerDataManager playerDataManager;
@EventHandler
public void onAsyncLogin(AsyncPlayerPreLoginEvent event) {
playerDataManager.loadPlayerData(event.getUniqueId());
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
playerDataManager.unloadPlayerData(event.getPlayer().getUniqueId());
}
}
the player left, save theyre data?
is there a spigot mixin tutorial somewhere thats not restricted to the october twenty fifteen version of the game
Ayo can we pin this fr
Didnt expect you to go into full code example damn, save it so you dont have to retype it xD
Ok
Ide just use a Lib or PDT tbh
Oh i see and by the time the player joins the data isnt saved remotely?
Yes
For that youll need to mark the servers data state as saving with redis
*twenty seventeen
and when you receive the callback of completion, mark them as completed in redis
Asyncplayerpreloginevent happens really early
An example usage would look like this:
public final class SpigotSandbox extends JavaPlugin implements Listener {
private PlayerDataManager playerDataManager;
private PlayerPersistenceHandler playerPersistenceHandler;
@Override
public void onEnable() {
this.playerPersistenceHandler = new PlayerFilePersistenceHandler();
this.playerDataManager = new PlayerDataManager(playerPersistenceHandler);
PlayerDataListener playerDataListener = new PlayerDataListener(playerDataManager);
Bukkit.getPluginManager().registerEvents(playerDataListener, this);
}
}
If you need the player data anywhere, then all you have to do is pass the PlayerDataManager instance there.
Theres no real reason to re-invent the wheel
and no
Thats why i reccomended a lib...
Like NBTAPI
It uses reflection
Or Bukkit API
*However this is a bit dangerous because if your server crashes, then your data will not be saved.
Thats why it it common practice to regularly persist the entire cache every few minuts.
PDC has existed since 1.14
^^^^^
PDC is godsend
Youll be reinventing the wheel with nbt unless your using remapped jar
Yes of cource. If you want to write custom data into NBT then just use a pdc
Welp
bump
NBTAPI it is
well...
Thank you very much for your time @lost matrix i'll deffo look into this 🙂 Don't fully understand everything but time to learn!
He is isn't he
it remaps all the bullshit d a b obfuscated names for you via reflection in this lib so you dont have to do it via NBT and suffer
Def. This is also important to understand if you want to stay in the industry.
Because basically everything is just CRUD
does anyone know this by chance?
technically as a storage format no, but in order to manipulate NBT data in minecraft you'll require NMS
You can use reflection
NBT-API has no nms import, only reflection
I'm used to using sql/mysql json, so this is a bit different
then check the slot index

nbtapi
Hey, if i set the persistent data of a player, would it persist after login and logouts, and server restarts?
for these items
This can be applied to any persistence method. yml, json, SQL, MongoDB. You name it.
Just implement the PlayerDataPersistenceHandler
no way thats betty white hitting the dab
uhh
idk how i feel about this, thats something new
checking index is way computationally faster than lets say a string or some kind of collection which does not provide O(1) random access
I just need an answer really quick
Considering the name Persistant, i assume so
meta data is stuff that will never save-
BRO WTF
BILL GATES HITTING THE DAB 2022 circa (colorized) 🥵 🥵 🥵 🥵
he looks like hes trying to make an F though, not a dab
he didnt bend his front arm
how would the saveDataAsync method be with json? Don't you have to rewrite the whole file in json? In sql you can just choose a record id right? Or do you store a file per player?
Do you still have my 2 classes for the BlockFinder?
One moment
Json you basically just overwrite the data in said file
@Override
public int getSize() {
return 5;
}
And have a file for each player
and the name of the file is theyre UUID
of its size
uhh not really
i can search for it real fast
Look at the essentials userdata folder, they do it like how i said on there 🙂
Can see a perfect example for saving your data there (Unles your wanting to split it up even further, essentials just shoves all the player data in the one file which may not be ideal if you wanna catagorize the data)
Okay thank you for the help you guys!
When should you use YAML to store data or when JSON or does it not matter
IMO i would never use YAML for storage, mostly everyone else will say the same
YAML for configs only
JSON read/write and parse is faster than YAML too, not a lot that its gonna make a worlds a difference, buts still faster
Anyone has any idea why my maven doesn't want to import mongodb 😆
Send ur pom
?paste
This is a trivial implementation for PlayerPersistenceHandler
https://paste.md-5.net/ipehixamic.java
It uses Gson as the bridge from live object to json
Wait what the
That class is built into spigot?
Is CompletableFuture a bit comparable with a task in C#
How is it used? Is there some type of handler/dispatcher like the commands/events?
This look awesome thanks
More with a delegate
Wait
No Task
yes Task is a good comparison
Nope this is just something ive come up with
You shouldnt shade in jetbrains annotations
Ahh okay, the name made it seem like it was made by spigot ahaha 🤣 was about to say dang ive done it wrong the whole time making my own system
how do i exclude it
scope provided
<scope>provided</scope>
The dependency looks good. Should work.
Did you reload maven
I rebuilt
reloaded all projects
tried different mongo versions
nothing
I can import it on gradle
but I don't know how shadowjar works
?paste
sec
https://paste.md-5.net/pohunerubu.cs
This is my gradle for another project, works fine as is
Compiles fine and runs fine with all libs
yeah but that's not spigot
Ive never needed to use shadowJar unless im wanting like to exclude stuff im not compiling in or whatnot, similar to maven
I need it to run from the plugin jar
https://gist.github.com/Flo0/23a00897a7c73e34a5eccbc702afc7e9
Try this out. Do like 10 steps per tick.
if i just compile it into a jar i get classnotfound exception
What was your old gradle file
How do you compile?
send it
oh sheesh thanks
i'll check it out after i finish this
How do you compile the plugin?
how
Isnt he using maven?
should show up in the list when you make it
I swapped my project from gradle to maven
For his gradle file he sent im talking about
because I didn't want to deal shading
but maven doesn't want to import mongodb for some reason
Maven has the maven-shade-plugin and gradle has the shadowJar plugin. You need to deal with them either way.
I personally find maven much simpler when it comes to shading.
yeah
yeah mavens definatly one click and go
Did u invalidate caches and restart?
how
In my custom chunkgenerator, how woulld I go about making the entire world Plains?
nope
doesn't work
only thing that gets imported is the bson
other stuff doesn't
that's why it's so weird
wait send the maven file again
Or whichever you were just building with that just did that
Weird its on maven central to hm
how do I use the shadowjar
When you create the task should just be a button like this one
Implement ChunkGenerator and implement the generateNoise(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, ChunkData chunkData) method
The actual shadowJar task seems simple though ive never made one
here sec
shadowJar {
archiveBaseName.set('yourarchivename')
}
IIRC it needs the baseName as a minimum
Just let another task depend on shadowJar. This way you also have a one click solution
That too ^
I am
But it seems that BiomeGrid is deprecated
what do you mean by archive
jar name essentially
archive is just another word for jar in a sense, the finished product
you can also
do i put that at the end of my build
Didn't you switch to maven?
not sure about that part ngl, i know gradle is bitchy sometimes about that
Or did you switch from maven
One moment let me take a look. Didnt work with that for a while.
I switched from gradle to maven because I didn't want to meddle with shading
On this project its near the middle so i guess it doesnt matter where the task goes, just needs to be in global scope (Not nested in anything unless somethings depending on it like smile said)
and then I found out my maven doesn't import mongodb
for some reason
so I have to use shadowjar
Olivo when profile picture 😦
Whats up. What would be the best way to load a chunk before player teleports there? I'm creating a random tp plugin and I don't want the player hovering in the void for 3 seconds when teleporting cuz the chunks are loading.
Ur chunks take 3 seconds to load 👀
Hey is it normal that pdc doesn't go between two plugins?
When people stop asking for it
Because each plug uses its own namespace
Can you explain a lil more?
That's why namespacedkey take your plugin
Its because its new chunks
Ah
You need to call generate first and then tp him
Makes more sense
https://paste.md-5.net/cizukoxaje.rb so like this?
you can call generate on existing chunks iirc, it should harm it unless your using the force setting
Wait so if I reference the plugin i want to share it between in the namespacedkey it'll work?
oh!
Yeah thattl do
You can create a static instant for both plugins
have one soft depends on it and use ThatMainClass.INSTANCE from both plugins, relativly easy for that part
won't it need to hard depend?
either or
prolly yes hard depend
since your gonna be directly using it and its essential for both to be running
Brilliant
It's because i'm making an economy system but with physical currency instead of virtual
Which class provides that method?
think it's working now
So i want to make sure the currency is unique
Ahh i see then yeah definatly hard depend both plugins
Chunk should or its in Location
99% sure its Chunk
1% is my insecurities
Neither of those has it.
World has regenerateChunk
ahh i think
its load(true) but
i need to check docs
2 mins
declaration: package: org.bukkit, interface: Chunk
aha
yes
but that didnt work, iirc someone said in the forums that if there are no players in radius it gets unloaded again.
Anyways I tried it and it didn't work.
Yes but its taking so long because they need to generate
Would a bukkitrunnable be a good way to store the data every 5 minutes?
Hence why you hover for a few secs
Yessir just make sure its async runnable
So you think I should delay my teleport more?
so loadChunk
and then wait like 5 sec
Currently I'm waiting 3 sec
You could do that yes, or call the load() first, and then setForceLoaded(true) (https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Chunk.html#setForceLoaded(boolean)) KEEP TRACK OF THIS CHUNK!!!!!!!!!!!! This method is dangerous!!
then you can tp him
i find that my server can generate and send to a client about thirty chunks per second. I'm unsure if the cpu or the connection is the throttle though. You should be fine waiting three seconds i guess
The method is dangerous because if you load shitloads of chunks, those chunks wont clear out
Yeah 3 seconds for a rtp is 100% resonably plus you can add fancy effects too
Yep thats the best way
Just dont use it when searching for a safe location
thats the main issue when using it
cough accidental dos cough
(I learned that the hard way)
But should I only load 1 chunk?
Yes
One is fine no?
Yes one is fine, i had nicer effects loading a 3x3 when i made mine though
just better TPS performance overall somehow
but one was still fine
How does it work tho? If you load just one the others will load faster and easier?
the others around the one you just loaded
i loaded the 3x3 before the player TPd
i used a CompletableFuture and called all those methods for the chunks effected
They won't be in the void
oh my god
The rest will load around them
it finally works
and in the callback, i teleported the player on future completion
Chunks can be loaded async!?
Uhh then why use a future?
Just easier because you get the callback from the future
so you can easier see the flow of whats executing
... 💡
I'm going to make a plugin that loads chunks in front of you if you move exactly north, south, east, or west, and snaps boats on blue ice to cardinal directions
nether highways will work so much better
IE like this
So loadChunksAroundLoc(loc).thenAccept((listOfChunks) -> { // teleport, chunks are all loaded and ready for us to use });
How do I stop NotNull from shadowing in gradle
Like just highways of ice?
compileOnly?
This is what i got so far:
A generator that generates a square world and afterwards only a bedrock ocean
yes, those things are fast. Servers tend to lag out when travelling at high speeds, with blue ice and elytras specifically
im more doing this because of elytra than boats
I'm trying to make it a terrain though
if the chunks arent loaded you get rubberbanded
This is what I have so far
and thats bloody annoying
havent messed with blue ice yet ill need to take a look
*the chunks you travel through
public class TerrainGenerator extends ChunkGenerator {
private boolean generateStuff;
public TerrainGenerator() {
generateStuff = true;
}
@Override
public void generateNoise(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, ChunkData chunkData) {
if(chunkX < 2 && chunkZ < 2 && chunkX > -2 && chunkZ > -2) {
generateStuff = true;
return;
} else generateStuff = true;
for(int y = chunkData.getMinHeight(); y < 61 && y < chunkData.getMaxHeight(); y++) {
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
chunkData.setBlock(x, y, z, Material.BEDROCK);
chunkData.setBlock(x, y + 1, z, Material.WATER);
chunkData.setBlock(x, y + 2, z, Material.WATER);
}
}
}
}
@Override
public boolean shouldGenerateNoise() {
return generateStuff;
}
@Override
public boolean shouldGenerateBedrock() {
return generateStuff;
}
@Override
public boolean shouldGenerateSurface() {
return generateStuff;
}
}
and I'm trying to make it only generate plains biomes, because an ocean biome .. surrounded by water .. is dumb
Also if you could let me know if I've done it in a super inefficient way or if this is fine
This is the first time I'm really digging into worldgen
you can set the biome but that wont change the blocks there
it will change grass block looks tho
nah not that sadly
all thats on you to do
world gens are pretty complex ngl
people who make those are a different breed
they scare me
superflat should be easy to generate
its just generating blocks at a set y axis infinitely
actually if you use the plains preset it generates trees, flowers, and small ponds
public void saveAllPlayerData() {
for (Map.Entry<UUID,PlayerData> data :
playerDataMap.entrySet()) {
if(data == null) {
continue;
}
playerPersistenceHandler.saveDataAsync(data.getKey(), data.getValue());
}
}
Would this be good to put them all in a different operation or should happen in one async method instead of another per player
Ohhhh
youre thinking about the normal superflat
eh the one time i tried generation i got a diagonal line of blocks
just bc theres so many
I mean so I guess I should just do custom terrain then right
This is kind of ok. But data is never null
was a structure actually
every chunk whose added x and z coord was a specific number generated that
i made sure to contain them in the chunk
not too big
but still weird that going north and east sixteen blocks gives you another copy
as said
supposed to be random
Okay thanks
i need to take a look at how math random seeds and massive numbers interact
cuz i bit shifted the z value by ten i believe then added the x value
Btw why dont you just have a void outside the generated chunks?
Sht well 1.8.8 doesnt have that method
So if I just load the chunk it gets unloaded pretty quick
I assume
NMS maybe
CUz when I get there I'm still in the void
or reflection
Might be able to access that method that way
Dont exactly have time to run through something like that rn haha
Let me check. Wasnt there an article on how to handle nms block placement?
Ok lets see what we can optimize here
what about setSaveChunk in chunkUnloadEvent
it saves the chunk on disk
what does that mean?
@lost matrix i put my project on github and wanna credit you how do you want me to do it? Like what name or something
That would be significantly easier lol
but I'm trying to make it like in 0.30
First of all:
if (blocks.containsKey(chunkKey)) {
blocks.get(chunkKey).add(new NMSBlock(pos, blockData));
} else {
final List<NMSBlock> value = new ArrayList<>();
value.add(new NMSBlock(pos, blockData));
blocks.put(chunkKey, value);
}
Should be
blocks.computeIfAbsent(chunkKey, key -> new ArrayList<>()).add(new NMSBlock(pos, blockData));
It does the same just with some fewer cpu cycles.
@weary geyser
public class TerrainGenerator extends ChunkGenerator {
private boolean generateStuff;
public TerrainGenerator() {
generateStuff = true;
}
@Override
public void generateNoise(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, ChunkData chunkData) {
if(chunkX < 2 && chunkZ < 2 && chunkX > -2 && chunkZ > -2) {
generateStuff = true;
return;
} else generateStuff = false;
for(int y = chunkData.getMinHeight(); y < 61 && y < chunkData.getMaxHeight(); y++) {
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
chunkData.setBlock(x, y, z, Material.BEDROCK);
chunkData.setBlock(x, y + 1, z, Material.WATER);
chunkData.setBlock(x, y + 2, z, Material.WATER);
}
}
}
}
@Override
public boolean shouldGenerateNoise() {
return generateStuff;
}
@Override
public boolean shouldGenerateBedrock() {
return generateStuff;
}
@Override
public boolean shouldGenerateSurface() {
return generateStuff;
}
This one
7smile7
But you dont need to
Then this:
final Chunk nmsChunk = ((CraftChunk) this.world.getChunkAt(new Location(this.world, pos.getX(), pos.getY(), pos.getZ()))).getHandle();
Can be improved:
final Chunk nmsChunk = ((CraftChunk) this.world.getChunkAt(pos.getX() << 4, pos.getZ() << 4)).getHandle();`
Dont see any other low hanging fruits there
Yeah caching the chunks might be a good idea. Not super important tho.
I mean this looks fine, no?
I think so
Except I seem to have some random problem going on here lol
https://cdn.discordapp.com/attachments/981614238885892138/991107679185547354/unknown.png
With a
Map<Long, Chunk>
And computeIfAbsend
Or you can group the locations by their chunk id (long)
None of those are worth doing
Chunks are cached internally anyways.
So after the first getChunkAt() call it doesnt really matter
You will only play for micros at that point
It would be async. So you would have to completely re-write your method
And it would be a lot more complicated
CompletableFuture isnt too complicated tbh
getChunkAtAsync().thenAccept((theChunk) -> {
// do your SYNC stuff here, main thread here!!
});
Does it need to be a bulk method? Because getChunkAtAsync() might spread the placement over
several ticks
Doesnt Future have a way to execute multiple futures at once?
I know javascripts Promises do
CompletableFuture.allOf(. . .)
Well... then going for nms stuff is pretty useless. You can easily place hundreds of thousands of blocks
in one seconds with the spigot method by simply spreading it over 20 ticks
Well. Whats wrong with using fawe?
edit the file manually 
I can do probably billions per seconds if you give me a good CPU and an NVMe with enough PCIe lanes.
Ill just pump out a gazillion region files with only stone in them.

@lost matrix i've implemented the code you sent me to the best of my ability but I don't really see anything happen
I'm stepping it 10 times per tick like you said
Oh yeah. There is quite a bit more you have to do.
So all this code does is find a suitable block in your surroundings.
You still need to add a simple pathfinder goal and let the entity wander to that block.
(When one is found)
public class BlockFinderTask implements LoopingTask<SuperiorHorse> {
@Override
public int getIntervalTicks() {
return 1;
}
@Override
public void runLoopingTask(SuperiorHorse superiorHorse) {
for (int i = 0; i < 10; i++) {
superiorHorse.getBlockFinder().step();
}
}
}
LoopingTask is an interface that I've created (i'm 100% sure it works i use it everywhere)
so how would i get the block that it's targetting though
Just use the nms pathfinder goal
Also this task should be inside the SuperiorHorse tick method (Im assuming SuperiorHorse extends the NMS horse)
public class TerrainGenerator extends ChunkGenerator {
private boolean generateStuff;
public TerrainGenerator() {
generateStuff = false;
}
@Override
public void generateNoise(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, ChunkData chunkData) {
if(chunkX < 16 && chunkZ < 16 && chunkX >= -16 && chunkZ >= -16) {
generateStuff = true;
} else {
generateStuff = false;
for(int y = chunkData.getMinHeight(); y < 61 && y < chunkData.getMaxHeight(); y++) {
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
chunkData.setBlock(x, y, z, Material.BEDROCK);
chunkData.setBlock(x, y + 1, z, Material.WATER);
chunkData.setBlock(x, y + 2, z, Material.WATER);
}
}
}
}
}
@Override
public boolean shouldGenerateNoise() {
return generateStuff;
}
@Override
public boolean shouldGenerateBedrock() {
return generateStuff;
}
@Override
public boolean shouldGenerateSurface() {
return generateStuff;
}
@Override
public boolean shouldGenerateDecorations() {
return false;
}
@Override
public boolean shouldGenerateCaves() {
return false;
}
@Override
public boolean shouldGenerateMobs() {
return false;
}
@Override
public boolean shouldGenerateStructures() {
return false;
}
}```
Does anybody know why it appears insisting on not knowing what chunks are within x 16 and -16 & z 16 and -16?
https://i.imgur.com/fPVz2ju.png
SuperiorHorse is more of a wrapper which contains the nms Horse and bukkit Horse
with a bunch of other util functions
Uhm... thats a super weird approach because the bukkit horse already wraps the nms horse
i know its weird but i have a reason
i first tried to do everything within the nms horse
but it caused spigot to desync with nms
for example if i set the horse armor with nms, and then tried to get the horse armor using spigot
spigot would say there is none
so I basically try to do everything on the bukkit entity, but if I can't then i resort to the NMS entity (such as for pathfinding)
public class CoolHorse extends Horse {
public CoolHorse(EntityType<? extends Horse> var0, Level var1) {
super(var0, var1);
}
public void setArmorThroughBukkit(ItemStack armor) {
((CraftHorse) this.getBukkitEntity()).getInventory().setArmor(armor);
}
}
NMS Horse with bukkit bridge for the armor
well too late i already built like my entire plugin based on this system
big oof. How do you even keep track of the horses when they are being unloaded then?
If a horse gets unloaded with a chunk and loaded again later, how do you persist the data?
Any changes I make to the SuperiorHorse will automatically update the persistent data container of the horse
I see
Thats expensive
so that if the server restarts, it basically kills the original horse and replaces it with a new version of the NMS horse
Do you extend the nms horse at all?
yes
i have a SuperiorHorseEntity which extends the nms horse
which is contained within SuperiorHorse
very quick question, how do you get a world? I want to set a gamerule, and i think i need the world to do that.
Can someone help me with my english? How would you call it when a player is in lava or water? Player is in liquid? xd
Ok. Inside this nms class you need to step the finder algorithm until it found a block or is done and didnt find a block.
If it found a block you need to let the horse have a different AIGoal -> Pathfinding to the found loction.
Sure
By name? By UUID? By object inside the world?
wait so first of all how do I get the target block that the blockfinder has found
and how would it navigate around obstacles?
yes
how lmao
Not 100% sure, but I think by string, cause I want to set a gamerule for that world and need a reference to it, so I think its name would work
would I use getNavigation().moveTo() for a bunch of different block positions?
Do you want to set the gamerule of the world a player is currently located in?
Yes
the just call player.getWorld()
@lost matrix So what I'm getting so far is this:
Override the tick method of the NMS horse, make it step the algorithm 10 times. (with a super call first of course)
Create a pathfinder goal that will start if a target block is found by the block finder, and finish when the horse can no longer reach that block or its hunger/thirst requirement is done.
but how do I get the target block from the block finder, and how would I make the horse navigate around obstacles?
The BlockFinder only finds Blocks the horse can navigate to. So all you need to do is let the Horse navigate to the Block at once.
with one getNavigation().moveTo()?
Actually the StepAlgorithm needs to be adjusted.
step() should return a StepResult instead of a boolean.
[SUCCESS, PROGRESS, FAILURE]
is StepResult a custom enum?
Yes it should be a custom enum
ok done that
does someone know how I can set the log level per thread in logback?
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%level] [%thread] %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
My log looks like this:
.....
01:13:25.586 [DEBUG] [JDA MainWS-ReadThread] Setting incomplete count to 1
01:13:25.587 [DEBUG] [JDA MainWS-ReadThread] Starting 75 second timeout for 1 guilds
01:13:25.664 [INFO] [JDA MainWS-ReadThread] Finished Loading!
01:13:25.666 [DEBUG] [JDA MainWS-ReadThread] Finished setup for guild 988732516372480020 firing cached events 0
01:13:25.723 [INFO] [main] Successfully logged in to Discord
01:13:25.732 [DEBUG] [main] Registered command "help" to executor com.jeff_media.quizbot.command.commands.HelpCommand
.....
I'd like to set the log level to debug for my "main" thread, but only to info for the "JDA MainWS-ReadThread" thread
what parts of the algorithm should return what tho
could this have something to do w regions?
@lost matrix as a reference here is my whole SuperiorHorseEntity
https://mystb.in/
wait I’m an idiot I didn’t send the actual code 🤦♂️
there
?paste
Ohh thanks
I managed to make a plugin that hangs the server without any loogs
Any idea why this always says the slot's size is 0?
public void addItemToRandomSlot(Player p, ItemStack item) {
List<Integer> slots = new ArrayList<>();
for(int i = 0; i<35; i++) {
if(!(p.getInventory().getItem(i) == null) && p.getInventory().getItem(i).getType() == Material.AIR) {
slots.add(i);
}
}
Bukkit.broadcast(Component.text("" + slots.size()));
Random r = new Random();
int slot = slots.get(r.nextInt(0, slots.size()));
p.getInventory().setItem(slot, item);
}```
```java.lang.IllegalArgumentException: bound must be greater than origin```
is there any way to debug it
my plugin has a part about reading the log
maybe it reads the log and every time it logs
your edge case is an empty slots list. in which case r.nextInt(0, 0) errors
how do you read the logs
getting root logger then adding appender
Yeah but why isn't anything added to the list even though the test inventory has empty slots
because iirc getItem(int) on an inventory would return null for an empty slot
can you share some code ?
Oh so I have to use ```if(p.getInventory().getItem(i) == null || p.getInventory().getItem(i).getType() == Material.AIR) {
Yea
should also obviously check if slots is empty
else your code errors when someone has a full inventory
hmm
so until reading the console it works
but then I send it to websocket
using this library
https://github.com/TooTallNate/Java-WebSocket
maybe it logs stuff when I send?
but the thing is I don't have any sockets open so it shouldn't send in the first place
Is there any library in Java for some "time parser" with a String? Like 3h would give me whatever it could be whatever ms there is in 3h or just a new Date + the 3h
Preferably that doesn't require me to pass in a full date string like 0d 3h 0m 0s
Is there a way to launch a player more than ~60 blocks?
Which one for example? Should look smooth
In the y axis or x/z?
y axis
#setVelocity
Already doing that, but no matter how high I set the y the player is still not launched more than 60 blocks up
yeah 4 blocks/tick is the maximum veloocity
you have to repeatedly launch the player every tick until the player is at the point in which they will be able to reach 60 blocks
hm okay
anyone can help me please?
just read the exception
Somehow cant find the wiki article on it, but understanding basic Java exceptions is a must
getEffectivePermissions
and loop that
I mean
PermissionAttachementInfo encapsulates PermissionAttachment basically
hey I'm new to config stuff, how would I access the encircled objects in an arraylist?
U can get it as a set
Not arraylist
Config#getConfigurationSection("Parkour.1").getKeys(false)
ah ok thanks a ton then
That just gets the naems
There is probably a library those already Pvbble, wouldent be surprised lol
Check that out on how they did it
and then you can make it from that
Personally id overcomplicate it
Make a good few objects, few enums etc
whole constructor to create a tree in real time
I have an ItemStack being a placable block with a PDC, is there a way to check when this item gets placed?
https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/block/BlockPlaceEvent.html#getItemInHand()
declaration: package: org.bukkit.event.block, class: BlockPlaceEvent
^^
what's a good "happy animal" sound
dog whining
jesus
ty
Player xp levelup
purple advancement sound'
mmm
i finally made it. After SO MANY ATTEMPTS ITS FULLY SYNCED
fully hidden player's inventory contents, you cant interact with player inventory at all
and it restores to the previous state after inventory has been closed
A library could’ve done for you lmao
hopper gui?
inventoryframework
thats simple
this is packet based, so no storing of items is done
whats the point of that
lemme show you
resource pack uis can now overlay the player's inventory
by using technique with font bitmaps
you can make interactable menus without having items inside the GUI, which can be accidentally moved and due to ping the overlay would wobble in that case
with trading gui
you can do that but in that case any player's contents will be visible through the overlay
but this is mostly for uis that are big
for example you cant create item model that can overlay contents
bigger than a scale of 4
for trading gui scale of 4 isnt enough to properly overlay
you know thats a smart approach now that I think about it
just making it look like the item was never put in the inventory
by manipulating packets
I've been dwelling on how to do something similar.
im not sure if IF would hide player's inventory contents, since it requires either storing the player's items or manipulating container synchronization
here's the packet handling in action
armor slots are not being removed while ui is open
this is actually a neat concept dude are you going to open source your code?
i think so, im working on UI lib rn so
it was a pain in the to make it
I haven't even gotten to custom textures yet I'm still working on base stuff
its very hard since player's inventory is really hardcoded so i needed to inject packet handling and send packets manually to the player to sync it also, i needed to prevent PICKUP_ALL action from collecting items of the invisible player's inventory contents, so i needed to remove literally Slot objects from NMS container menu in order to achieve full sync
https://github.com/Y2Kwastaken/ArcticInventories/tree/revised this is what I got for my lib so far. I haven't even touched custom textures yet though
cool
public void onMenuClick(InventoryClickEvent e) {
if (e.getCurrentItem() == null) return;
if (e.getView().getTitle().equalsIgnoreCase(ChatColor.YELLOW + "Punishment Menu")) {
if(e.getSlot() == 13) {
e.setCancelled(true);
e.getWhoClicked().sendMessage("Stop That");
}
}
}
}```
can someone tell me why this is just not registering the click
i've tried checking the material, the display name and the lore
did you register the event
//GUI COMMANDS & GUI EVENTS
getCommand("punish").setExecutor(new PunishCommand());
getServer().getPluginManager().registerEvents(new PunishGuiListener(), this);
yeah
lol?
you need the @EventHandler annotation
you don't have one
happens toe veryone
yo
another question'
i'm struggling really bad with giving a variable to another class
it's breaking a lot
?di
Guide to dependency injection: https://www.spigotmc.org/wiki/using-dependency-injection/
Learn more Java before coding a plugin then
Di is an industry standard
How can I implement dialogue as a part of my plugin? As in ask a question, get a response back and then ask another question based on the response(already set responses ofc), etc.?
How can I achieve a chat colour gradient like the one below?
Is there a way to change the max amount of hunger meatsticks similar to how you can change the max amount of hearts?
And also bump this guys question cause this is a really cool effect and I wanna do it too
I believe if you search up hex gradient generator, you can make a gradient and it'll give you the hex code, which you can apply to the message
gotchu, thanks
so essentially all of this is shoved into one ChatColor.of?
This is a good website for the generator: rgb.birdflop.com
Yea I think so
okay! thanks
If you have a question, please just ask it. Don't look for staff or topic experts. Don't ask to ask or ask if people are awake or available. Just ask the question to the channel straight out, and wait patiently for a reply. Make sure you use the right channel regarding the topic of your question. Create a thread in case the channel is already in use!
ok
so im trying to make a loot crate
where the player right clicks the item
and then it subtracts one and then gives them loot
i figured out the right click and the subtract but not the loot
i have certain items i want to give them but i dont know how you would pick some from those
Store the items in a database and then query them based on chest opened? Use a yml config? I don't understand your exact dilemma.
You sent it in java bytecode looking stuff lol
so do i need to code a random function?
What did you send us lol
LootCrate.asm
Lmfao
Yeah if you're doing asm then you'd definitely need to write one yourself there
ok, will look into it. so then i just call the random function to give the list of items?
Not an asm expert. This is after all a java focused server
ah okay ill try to ask on minecraft forum, thanks!
that would be something
its like the shit that i sent in this server sometimes
fn main() {
println!("Hello, world!");
let binding = core::iter::Iterator::collect::<Vec<u8>>(core::iter::IntoIterator::into_iter(0u8..=8u8));
let bytes = Vec::<u8>::as_slice(binding.as_ref());
println!("{}", usize::from_be_bytes(core::result::Result::<[u8; std::mem::size_of::<usize>()], std::array::TryFromSliceError>::unwrap_or_else(core::convert::TryInto::<[u8; std::mem::size_of::<usize>()]>::try_into(&bytes[1..][..std::mem::size_of::<usize>()]), |err| { std::process::exit(core::iter::Iterator::map(core::iter::IntoIterator::into_iter(String::as_bytes(&ToString::to_string(&err))), |b| *b as i16).sum::<i16>() as i32) })));
}
Does anyone have an idea how I would check if a player is falling?
velocity?
yeah
What I'm currently using is checking #getVelocity().getY() < 0
but this is kinda buggy since I found out the main y velocity when standing around is -0.0078
Also check if they're on the ground ig
Is there a way to calculate like the gravity or smth?
currently on my server the main y velocity seems to be -0.0784000015258789 and idk if this can be changed or smth
What're you tryina do?
Checking if a player is falling and as soon as he hits the ground do stuff
currently having a runnable firing in the move event
already taken care of that
Can't a runnable that checks if the player is on the ground each tick sort that for u?
If not on ground and velocity negative falling
If on ground, falling stopped
^^ if they were previosly falling
yeah thats all working out the only problem is the event keeps firing like 20 times after im cancelling the task
What event?
I'm spawning a firework as soon as the player lands on the ground and it keeps firing like 20 times
can't get it to fire only once
Can u send code?
When they're falling, put them in a set called falling
When they're onnthe ground, if they're in the set, that means that the player fell
So you can do whatever and then remove them from the set
I'll try that give me a sec
That way when the runnable checks on tje next tick and sees the player on tje ground, it does nothing since they're not in the set
is there a way to get all the structures that exist as a list. Structure manager shows it have none in it
Random can return the same value multiple times
set the seed to system time in nanoseconds
isnt it just that he initialilzes it too fast?
idk]
probably is:
Additionally, default-constructed instances do not use a cryptographically random seed unless the system property java.util.secureRandomSeed is set to true.
I think its just using the system time in millis as seed, but i could be wrong
Not a dev related question but maybe someone can help me out, are there any other MLG types in MC besides water bucket, cobweb and haybale? (ignoring slime blocks)
ladder
latter
honey blocks
random should have a setseed method. I'm unsure if it works in this instance, but you could check if ThreadLocalRandom#current#setseed#nextInt works
end portal
you're actually getting the same number every time?
its possible that your jvm initializes the same way every time
What about using SecureRandom ?
oh yes of course, ty!
lava bucket
https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html It's pretty much the same but safer
anyone know how to get the windowid of the inventory a player is in? ive tried doing this but it just opens a wrong inventory, and doing some debug on client and server shows the id this returns isnt the same one the client opens
use a for loop
no like
for (int i = 0; i< 1000; i++) {
like that
and print 1000 random numbers
Ok 2 layer
then something si wrong with your computer
why dont you just use math random
multiply it by your maximum value + one, then cast it tointeger
No worries, why do you need to multithread it btw? 😮
Hey guys !
Quick question about the docs !
I'm reading this right now : https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/player/PlayerAdvancementDoneEvent.html
And was wondering, looking at the getAdvancement() method, I see that it returns the completed advancement.
How can I know on which form it returns it ? Like how do I know how to compare it with an existing advancement please ? 😄
declaration: package: org.bukkit.event.player, class: PlayerAdvancementDoneEvent
It returns an advancement object
To compare it you can compare the keys
Of the advancement
Not sure if there's a better way
Advancement#getKey
could you help me with the formatting? i'm not quite sure how i am supposed to do this
Okay thanks a lot, and how do I know what a key look like and matches which advancement ? In the docs ? 🤔
a key is a namespacedkey
it's made of 2 parts, the namespace and the key
hence the name
the namespace can be for eg. bukkit or minecraft or your plugin name
the key is like the advancement name or whatever
just do key.eqauls(otherKey) to compare em
Ok I see ! Thanks a lot for the quick course, really helpful ! ❤️
Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName).toList().toArray(new String[0]);
shorter^^
String[]::new 🙂
:o
Why does List#toArray require an array
And the method that doesn't requires casting
when i try to register login authme with bedrock account in java server there come cheats are not allowed
how can i fix it
It says "Can't resolve method toList in Stream" How do I fix it?
just use toArray directly
But then u have to cast :(
nope
Really?
why would you if you already pass in the type
toArray(IntFunction<A[]> generator)
the length
toArray(String[]::new)
Or Just use an Array of length 0
So .toArray(new String[0])
Oh actually that is stream
ye
Probably works either way heh
@EventHandler
public void onAdvancement(PlayerAdvancementDoneEvent e){
Advancement advancement = e.getAdvancement();
Player p = e.getPlayer();
if (advancement.getKey().equals(NamespacedKey.minecraft("story/upgrade_tools"))){
p.sendMessage("action to do here");
}
}```
I'm doing something wrong I think, but can't really figure out what 🤔
uhh
Gotta Love consistency
are u sure the upgrade tools namespacedkey is story/upgrade_tools?
because its a function to explicit call ::new
I'm not 100% sure, I didn't really know where to find the info, found on the fr-minecraft.net website that they display the ID of advancements
So I assumed it was it xD
String[] names = Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName).toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int i) {
return new String[0];
}
});
it requires an intfunction just to create an array the size of the stream???
ye ik but like why does it need it in the first place?
the int is the array size
it just initializes an array with the specific size necessary
yes but why cant it just do that internally
or why does toArray() return an Object[] and not T[]
it's just stupid
Bukkit.advancementIterator().forEachRemaining(advancement -> System.out.println(advancement.getKey()));
@shy shadow
the IntFunction also gives it the type so that it can return it as T
put that to see all the advancements
lol
Ooh thanks, I was doing something similar to reach that too haha
p.sendMessage(String.valueOf(advancement.getKey()));
Tried to do that on the event xD
that's also possible ye
also this
why cant it just be a List<Player>
if i want it to be a list<Player> i need to cast it
i think its a set and even an array on some older versions
omg minion I'm so sorry
I've been trying this for 2 hours and just realised I didn't registered the event LOL
Because of generics erasure - it must somehow get an instance of Class<T> in Order to create T, which in your Case is Not applicable
Hahahaha minion imma go back to sleep
I was also connected on the wrong server
XD
Btw it works perfectly now, thank you very much for your help !
Ohh cuz they used ?
Iam creating a random teleport plugin. My goal is to load the chunk before teleporting there so the player won't hover in void. I'm on version 1.8.8. How could I achieve that? I can do chunk#load() but I can't set it to be force loaded so it unloads before I get there.
if you load the chunk without any reason to keep it loaded it will just be unloaded - you need to update to modern to use plugin tickets
So you cannot really achieve that in 1.8.8?
What about ChunkUnloadEvent?
I could cancel that.
Just use World#setChunkForceLoaded https://hub.spigotmc.org/javadocs/spigot/org/bukkit/World.html#setChunkForceLoaded(int,int,boolean)
declaration: package: org.bukkit, interface: World
oh that's also not available in 1.8 lol
I wonder if the 1.8 api has any features at all
just load it again on unload
Yeah but chunk takes time to load doesnt it? If I constantly do load() on unloadEvent it would be pointless.
that's how other chunk loaders do it in 1.8
@EventHandler
public void onInteractEvent(PlayerInteractEvent e) {
//Check if action was right click
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
e.getPlayer().sendMessage("test");
}
}```
for whatever reason its sending doubles of the same message and i dont know why
I'll give it a try.
the event gets called once for each hand
for the first time maybe, but after that it should be cached somewhere iirc
i see
and even that "takes time" isn't much
Official API for AquaCore - https://www.mc-market.org/resources/11118/ - AquaCoreAPI/src/main/java/me/activated/core/api at master · FaceSlap02/AquaCoreAPI
EW
