#help-development
1 messages · Page 862 of 1
so i can cast it to List<location> right?
Yes, Location is serializable so you should be able to get a List<Location> (assuming you actually serialized Location objects via the config API)
If you serialized them youself into a more compact syntax then you'll have to use #getStringList() and parse it yourself into a List<Location>
[ERROR] Failed to execute goal on project mxPlane: Could not resolve dependencies for project org.getkeesh:mxPlane:jar:1.0-SNAPSHOT: Failed to collect dependencies at nl.sbdeveloper:VehiclesPlus-API:jar:2.3.5: Failed to read artifact descriptor for nl.sbdeveloper:VehiclesPlus-API:jar:2.3.5: The following artifacts could not be resolved: nl.sbdeveloper:VehiclesPlus-API:pom:2.3.5 (absent): Could not transfer artifact nl.sbdeveloper:VehiclesPlus-API:pom:2.3.5 from/to sbdevelopment-repo (https://repo.sbdevelopment.tech/{repository}): Illegal character in path at index 32: https://repo.sbdevelopment.tech/{repository}/nl/sbdeveloper/VehiclesPlus-API/2.3.5/VehiclesPlus-API-2.3.5.pom -> [Help 1]
somebody can help?
Illegal character in path at index 32
Guessing that {repository} is the problem
?
What does that mean?
i.e.
assume A is air and B is stone, and that we are raytracing straight north (1, 0, 0) for simplicity, if we have a configuration as follows:
A A A A A B
the raytrace would return B, but I need the last of the As (the one adjacent to B)
Using a BlockIterator would be one solution. It will give you all Blocks [A, A, A, A, A, B]
... fair enough I did NOT think about that 😂
Just use the RayTraceResult https://hub.spigotmc.org/javadocs/spigot/org/bukkit/util/RayTraceResult.html#getHitBlockFace()
oml I am blind 😭
result.getBlock().getRelative(result.getHitBlockFace())
tasks {
register<Copy>("copyToTestServer") {
group = "test"
val testServerDir = File(System.getProperty("TEST_SERVER_PATH","/Users/mfnalex/mctest/"))
val pluginsDir = File(testServerDir, "plugins")
val basicsPluginDir = File(pluginsDir, "Basics")
val basicsModulesDir = File(basicsPluginDir, "modules")
if(!testServerDir.isDirectory) {
error("Test server directory does not exist! Specify the correct path as environment variable TEST_SERVER_PATH.")
}
if(!basicsModulesDir.isDirectory) {
basicsModulesDir.mkdirs()
}
from(project(":plugin").tasks.getByName("shadowJar", ShadowJar::class).archiveFile)
into(pluginsDir)
from(project(":modules:test").tasks.getByName("jar", Jar::class).archiveFile)
into(basicsModulesDir)
}
}
This shall copy the plugin into plugins/ folder and the test module into plugins/Basics/modules/.
When I only add one "from(..) into(...)" it works fine, but whenever I use both, then both files (plugin AND module) and up in the the modules folder??
do I have to create two tasks? because that'd be annoying
if this method is deprecated whats the propper way
Iirc it's deprecated because of string usage
Just use it if you really need to
im getting a player from username
But otherwise, use UUIDs
Just use that, it's deprecated so people don't use strings to get offline players or some shit like that I've been told
arl
If you wanna make sure the player already joined the server before I'm pretty sure the server stores a list of all players that ever played
fixed it using 2 copy tasks
val testServerDir = File(System.getProperty("TEST_SERVER_PATH","/Users/mfnalex/mctest/"))
val pluginsDir = File(testServerDir, "plugins")
val basicsPluginDir = File(pluginsDir, "Basics")
val basicsModulesDir = File(basicsPluginDir, "modules")
tasks {
val copyPluginToTestServer = register<Copy>("copyPluginToTestServer") {
from(project(":plugin").tasks.getByName("shadowJar", ShadowJar::class).archiveFile)
into(pluginsDir)
}
val copyModulesToTestServer = register<Copy>("copyModulesToTestServer") {
project(":modules").subprojects.forEach {
from(it.tasks.getByName("jar", Jar::class).archiveFile)
}
into(basicsModulesDir)
}
register("copyAllToTestServer") {
group = "test"
if(!testServerDir.isDirectory) {
throw RuntimeException("Test server directory does not exist! Set environment var TEST_SERVER_PATH to the path of your test server.")
}
basicsModulesDir.mkdirs()
dependsOn(copyPluginToTestServer)
dependsOn(copyModulesToTestServer)
}
}
is it still possible to make plugin for 1.7.10 i cant find spigot api
it is, but you should never
And what if I have a private server with a modpack in 1.7.10 and I don't have the choice but to make a 1.7 plugin 😂
a modpack? Then make a mod, not a plugin
plugins and mods aren't compatible
no, mods and plugins should never be combined for a lot of reasons, if you run mods, run mods
ok mister but its not what i asked
sounds like you are not using spigot 
exactly
i am
no, if you are running mods then it can already NOT be spigot
crucible
whaaa
and even more
if it's running mods then it's already not spigot, but a fork
Yea so, if you are running Crucible you are not running spigot
which means, go ask them where their API is hosted
lmfao
if the spigot repos don#t have 1.7.10 api artefacts then you are pretty out of luck xD
magma is 1.12 and crucible is a dead project i just want the spigot 1.7 api and ye it doesnt
there is no artifact anywhere
if you have the jar, depend on it
no like, the server jar
why build for 1.7.10 if you don;t have the server?
i can use the server jar ? :/
probably ?
i do ?
back then it was not a bundler setup
il try
click on the link
its not working
i tryed
it redirect to
Note: This page is not updated, for the latest information please see the wiki: https://www.spigotmc.org/wiki/buildtools/
It's been nearly 40 days...
try server jar yea
Bro this is some clean code
wdym cleaner this is good, you'd prob still easily understand it after a few months
If you Look at Ur code after a few months?
Hi idk if I should ask here or some other places but does anyone know if the graddle-wrapper.jar is open source?
hey, I know this must've been answered many times before but I can't find anything on google
my IDE says HoverEvent is deprecated, what should I use instead?
What does it say?
is this from TextComponent? It usually says when you hover, or on the javadoc page
Just says it's deprecated, not what to use instead or anything
Yeah, but doesn't say whay to use instead
Are you using paper @grave vale
Hey!
I'm having trouble with socket communication.
Specifically with the reading part.
I'm using ObjectOutputStream and DataInputStream.
Proxy - https://paste.md-5.net/nixabulosi.java
Bukkit - https://paste.md-5.net/zesutasuhu.java
I've tried lots of different stuff
Currently I'm stuck at only one message being able to be sent.
After the initial message, my proxy sends at the beginning of the communication, it no longer seems to accept any data, as the DataInputStream is blocking the thread by reading the UTF.
Any ideas of why it may be wrong?
For faster search in the code:
- if you want to see the code for listening to the incoming traffic:
listenvoid - if you want to see the code responsible for sending the messages:
sendDatamethod
Thanks in advance,
TomKo
it says on the javadocs that only on of the constructor is deprecated, there are other ones that are not
I have Plugin Messages setup, thats why I'm trying to make use of byte array communication, as the Plugin Messages work on that principle.
how do I use these?
ty
can I somehow get rid of this unchecked cast? If no, how can I suppress it in kotlin?
@Suppress("UNCHECKED_CAST") on the statement iirc
thx. there isnt a better way I supposed than to suppress it? I mean I already checked isSUperclassOf
or alternatively right click -> suppress for statement
BasicModule?>!! Totally
I mean, can't it be just a wildcard?
wdym?
KClass<*>
but I need a Class<? extends BasicsModule>
show how you use it
It’s just IJ being dumb tbh
I would just let it be a wildcard and cast it upon instantiation or wherever else you need the type
it's a compiler warning as well
He’s checking it above so it’s just kotlin being a derp and not smart casting enough
bump
it's because generics are erased, you'll have an unchecked warning in java as well
i know that generics are erased, but I a mliterally checking isSuperclassOf one line above
one could assume that the compiler would then know that the cast is not unchecked
it's just like reflection but with kotlin specific stuff
doesn't kclass have an equivalent of asSubclass or w/e?
don't think so
Classloading stuff in kotlin - that is a new one
it's just a regular URLClassLoader
maybe
why would that not be possible
yeah still I haven't seen such logic being done on the kotlin side of things yet
never event tried dual boot
As long as you have enough boot partitions
no try-with-resources
I think these days (under UEFI I think?) there is no limit that is inside sane bounds, so yeah - possible I guess
should have just used SPigotUpdateChecker 🥲
try-with-resources is not a performance thing but rather a sanity one
The URL input stream probably closes after a while but not closing it properly in case of an error can cause issues regardless
can you make spell particule not white like make them red?
that particle doesnt have any data that you could change
debian 12 on servers, but I wouldnt wanna use it on desktop
yeah well if I had to use linux on desktop, I'd also use debian there
im scared of using arch
right away
like
i used ubuntu and mint before
but i feel like thats a huge leap
leep
leap?
idk
eh
Debian 
i'd just stick with debian, it's a no-bullshit distro and the updates are flawless
it's no different than any other distro that i've used tbh
ubuntu sometimes breaks on major updates, this never happened to me on debian
Fedora
surely this guy knows what hes talking about
im just gonna trust him
he looks believable
Debian I am personally not a fan of, having outdated stuff is not great
Yeah this. I still use Ubuntu for desktop although the snaps (mainly Firefox) are a bit annoying
Firefox is annoying as hell even outside snaps lately
Well if you can call the occasional soft-crash (i.e. you can only use FF with your mouse - don't ask how) annoying
I'm still having issues with JarFileSystems - I can walk through the paths using walk() but whenever I call toFile() on a Path, it throws UnsupportedOperationException - I thought I would be able to access files as File object from within jars when using a JarFileSystem?
i think the kids nowadays call that a skill issue
What do you think a File is?
File is ALWAYS a file:// URL. JarFileSystem produce jar:// URLs tho
so can I acquire a file object of a file inside a .jar somehow without actually extracting it, or not?
Hence why you should not use java.io.File in your APIs
You can use the java.nio Path API - so use Files.newInputStream(path) or similar
Plus Path-based APIs are apparently a bit faster on some system than the old java.io File API
I have a .jar file in my .jar file and I need the "inner" jar as JarFile, which only takes a File object in its constructor
if I could just create a JarFile from an InputStrea mor whatever, that would be nice
performacne wouldn't even matter, I just need the inner jar as JarFile object lol
Why exactly JarFile?
what is your goal
Can't it be ZipInputStream or similar?
a ZipInputStream doesnt have getEntry etc for the contents
I want to access the contents of the inner jar file without extracting it
You can use a for loop
i need help
If performance is the concern (or if the files are plain massive) a library such as LL-Java-Zip also works (LL-Java-Zip decompresses on demand for example)
a ZipInputStream / ZipFile however also wouldnt check if a jar is properly signed etc right?
There are also jar file systems
i want to use a spiggot plugin called Gsit in my online minecraft server 1.20.1. I did the java file in the files. didnt work. did it in the plugin file. didnt work. i did the same on filezilla but it also didnt work. how can i get the plugin in the server.
I'm not sure whether signing stuff makes even sense
JarInputStream might verify the integrity, but you'd probably need to check manually
Yeah, JarInputStream does do some checking via JarVerifier
At least on Java 17
Ok i‘ll see if I can refactor everything to use inputstreams instead
However it does a few assumptions:
- The manifest should be the first entry in the META-INF directory.
- The .SF/.DSA/.EC files follow the manifest, before any normal entries
- Any of the following will throw a SecurityException:
a. digest mismatch between a manifest section and
the SF section.
b. digest mismatch between the actual jar entry and the manifest
However JarInputStream isn't actually JVM-compliant - or rather said it doesn't behave like the JVM would read a jar file.
afaik JIS is only really useful for signature verification and checking manifest stuffs if you want to use the manifest api
JarFile can still be useful as it can work with multi-release jars for example
but, that's due to the ability of random access, JIS is an InputStream in the end
did you know that gta vice city has 4 different taxi models?
Taxi, Kaufman Cab, Zebra Cab and the rarest Cabbie
Mojo? Like maven lifecycle goals or what?
how can I remove an specific suspicious stew recipe? I tried using the Recipe Iterator but I don't see any recipe matching with the suspicious stew material
You mean mojmap? MOJOs are maven lifecycle goals (well technically they are more like maven plugins, but it is complicated)
does anybody know how I can work on my Spigot-Repo fork to contribute? Whenever I clone and try to run ./applyPatches, I am getting ```Applying: Spigot Configuration
Using index info to reconstruct a base tree...
A src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
A src/main/java/net/minecraft/world/level/World.java
Falling back to patching base and 3-way merge...
CONFLICT (modify/delete): src/main/java/net/minecraft/world/level/World.java deleted in HEAD and modified in Spigot Configuration. Version Spigot Configuration of src/main/java/net/minecraft/world/level/World.java left in tree.
CONFLICT (modify/delete): src/main/java/net/minecraft/server/dedicated/DedicatedServer.java deleted in HEAD and modified in Spigot Configuration. Version Spigot Configuration of src/main/java/net/minecraft/server/dedicated/DedicatedServer.java left in tree.
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0003 Spigot Configuration
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Something did not apply cleanly to Spigot-Server.
Please review above details and finish the apply then
save the changes with rebuildPatches.sh
that isn't a thing, is it? You really need to get your terminology right
what
I guess it is what is on the tin. Resolve the merge conflicts and apply git am --continue, then do ./rebuildPatches.sh
Though obviously I would do a backup beforehand
it's my first time working on the repo
idk how I would resolev the merge conflicts as it is a freshly forked and cloned repo
i want laptops to have a little "hole" with a cover that lets you store 1-2 usbs sticks
like a little usb slot
I have literally forked it on stash half an hour ago
yes what? xD
You can use 7 zip
I think it is fairly safe to assume that that wasn't the right answer
lol
22:34:46 [SEVERE] Error authenticating xxx with minecraft.net
java.lang.IllegalStateException: Expected HTTP response 200 OK, got 429 Too Many Requests
I have this error when entering bungeecord does anyone know how to fix it?
anyone knows why gradle refuses to search for a dependency in sonatype snapshots even though it's obviously declared?
most likely belongs #help-server.
This likely is caused by you getting rate-limited by mojang. Don't ask how to work around that - I do not know
Perhaps snapshots are disabled by default in maven repos under gradle?
Only problem is that currently there are no people on the server and no connections....
Also, is this a multi-module project?
yes it is
Does a task of a parent or sibling module consume the configurations of the child project?
Ah yeah
core is the only place where I'm using it as dependency though
this is the build file for plugin
Yes, but your plugin module also packages the dependencies of your core module
you need it for plugin as well, since it has to resolve it as a transitive yes
via the shadow plugin
hm and how do I do that? I do not want to just copy paste the repository into the other module
if it gets the dependencies of other dependencies, shouldnt it also use the repositories that those other dependencies use?
I guess you could define a shade task in your core plugin and shade the shaded core jar? But that is a little bit hacky imo
you seem to already have a build logic composite module, so you can just define your repos in a base convention script
no
that is apparently behaviour that the maven artifact resolver does (though I was never able to verify that claim) - apparently it caused all sorts of security vulns
can you place block with 1 sec daly, i try with Thread.sleep, Bukkit.getScheduler but it doesn't work
?notworking
"Does not working" is a useless statement. Please describe what exactly is not working, what you expect it to do, and what actually happens. If you get any console errors, also ?paste the entire stacktrace.
?nocode
It’s hard to answer a programming question without code
Oh no! You ran into a problem. But no worries, people are willing to help, but first they need to see your code. This is because otherwise, they would be providing help based on guesses instead of concrete knowledge. Whether it be a compile error, runtime error, or an unexpected output, I'm sure that if you were to provide code, you'd receive a quick solution.
Thread.sleep ought to be avoided at all costs - use a task
yeah but I don't want to add arbitrary repos to subprojects that don't need them
?paste
https://paste.md-5.net/leliqigoga.java (with a new instance of java higher in the code)
this is usually how it's done
you can include only specific groups from a repository if you're concerned about security
sad. I'm not concerned about security, I just find it do be "dirty" to add random repositories lol
can't I tell gradle sth like "for each project that depends on another project within my project, add all repositories to the depending project too"?
not that I'm aware of
I can't find any information on registering custom enchantments in 1.20+. I wonder, is it still necessary to register? Do you need to handle your own registration? If so, why?
You shouldnt register any custom enchants but use PDC instead
Alright. Seems like you need your own registry implementation using PDC then
The Enchantment class isnt meant to be extended by plugins unfortunately:')
Oh well...
So you basically have to create a custom enchantment implementation from scratch?
yeah well you can still extend Enchantment and it will somewhat work
what won't work though is e.g. removing your custom enchantment again using API, that's because CraftBukkit casts Enchantments in the removeEnchantment method to CratEnchantment
so if you want to indeed extend Enchantment, you would have to extend CraftEnchantment
that change was introduced in 1.20.3
Ahh right. Then I'll be making it from scratch. Gives me better control over it anyways. Thx
np
i decided to still register exactly one custom enchantment anyway, to add the glow effect
check line 103 in Main
Hey guys im using velocity as my proxy and using Redis(Jedis) Lib to communicate between
proxy->backend servers. And i am wondering how the hell its possible to teleport the player to another players location on another server.
Would i make my command on my proxy plugin or in my spigot plugin? I am just so confused and i dont understand how it would work.
Ive looked at every link on spigot and bungee forums but all of them have same feedback and most of it is just copied and pasted from other threads. To no help
?pmc
Why does my config doesnt work? When I type "/crate givecrate username cratename 1" and then place is, it just opens the enderchest like a normal enderchest...
Console errors
The config you posted does not match the error
I just found out, that the errors was from a older version of the plugin that i deleted. The new plugin doesnt show any errors, but still dosent work with my config. The default config works just fine...
😦
I figured it out. Was bcs off the material was record_strad but that dosent work anymore, you need to use IDs
hi
I have a question on the spigot page can you publish resources not plugins? i.e. any configuration of x plugin?
Bumping my message, someone help me pls
I have no internet only phone data and this is my only resource right now.
Is there any good guides on how to properly organize files? Im not sure how to exactly, and right now im only seperating things by either them being a resource or a core part of the plugin
Yes
Its very possible
I’d start by defining a protocol, one from server to proxy and one from proxy to server
Then use that through redis
Wdym defining a protocol? Im not familiar with whatever it is your talking about
Hey everyone! Long time no see!
Does anyone have any experience with Java spring boot websockets inside Docker containers?
Hey, how do I register a command in 1.20?
well this is fun
I now have AI autocommenting my code
now when the documentation is bad I can blame AI!
How do developers maintain a data class thats saved in a format like json
Like for example if I change a variable name due to bad naming, how would previous versions update to the new name
you people
you can't realistically retroactively add features to previous versions of your software
what if it's like a database
but if you're talking about updating previous files and not previous software then I just use data converters that look for specific keys and change them on boot
Damn that's a lot of work
if it was easy it would be called your-
gotta say having AI in the programming workflow is actually a game changer
You would implement a data conversion mechanism
^
it doesn't really matter much if you're already proficient at what you're currently but if you're tinkering with a language you know relatively little about or working with a specific lib it can be pretty amazing the difference it makes
You can start defining version formats
hm
and define ways to convert between versions
version formats are for people who plan to fail with their data, I never plan to fail and thus I never fail
DataFixerUpper can partly be used for that
I'm thinking of a class like this
public interface DataFactory<T> {
T createDefault();
T deserialize(Map<String, TreeElement> serializedData);
Map<String, TreeElement> serialize(T data);
}
idk what TreeElement will be named
But it's the only name I got in mind rn
you think I can add the updater in the deserialize method?
depends, I mean maybe
I wish things with yml were that simple
i mean
rly?
technically yml is a map<string, obj>
Idk I don't really use yml that much lol
Yml has anchors, comments etc
oh
The semantic specification of yml is far more than a map epic
if were talking about just values yml is just a map, but if we talk abotu the rest yml is wild
oh I also wanted to know
myea well yesnt
How much is my servers performance gonna hurt for constant hashmap look ups
wdym by that
you better not be doing io operations on the main thread
HashMap::get ?
yes
that's very fast
Not too much
do you think I can get away with 1000 a tick
Try and see
easily but do you really need it
Extreme example
idk I might lol
Depends on players
And the custom enchants, quests, etc the amount of that
I'd be shocked if you can even see that have any kind of impact in the timings
alr maybe ima test it
what you do with what you got from the map is likely to be heavier than getting the contents in the first place
but again do you really need it
there are caching strategies you surely can use if it's that volume of data
cache your cache
idk if this is a good system
or in other worlds aglomerate the data, if you need 100 data points per player don't put 100 primitives in 100 maps, make one object with 100 fields
PitPlayer
DataContainer persistentDataContainer
DataContainer sessionDataContainer
sessionDataContainer might be stuff like combat timers
persistentDataContainer might be stuff like gold, xp, stats
This is 1.8 so I don't have the PDC api
so are you planning for 1000 players logging in per tick or something
how are you estimating you might access a map like that 1000 times in a tick
well let's say I store cooldowns in the sessionData
And I got
idk it's just a question alr
Main issue isnt going to be so much hashmaps in memory being accessed rather how is the data obtained and updated in the hashmap. Also concurrenthashmap exists
It's just .gey
.get
And when the player joins, it's .put
One word: Implement it yourself
I am aware. Also just be aware that hashmap isnt always good with small data sets
Sometimes its better to use an array in such instances. When your data set is small the hashmap ends up with too many buckets being underutilized
How could I know where the client wants to go. My goal is to know if the player is pressing any movement key to create a vector and impulse It there to create a dash, I have already tried with playerMoveEvent but It isnt acurrate because when a player jumps Its motion is awkward
Have you considered taking a rolling average? Might be smoother.
bump
like sort them into packages?
would be interesting to make this work for morphia... 
I mean deffo possible
just... seeing if there's any inbuilt ways
Morphia?
Morphia, for mongodb, a framework for java for entities
I did research and figured it out, proper organization of packages
But now im unsure why my YAML config isnt working with hashmaps
One way I could do it is have annotations and a version id assigned to each object, storing what version the object is from, and when the object gets deserialized from MongoDB, check that field and if it's lower than the current version, scan the fields and update them accordingly. I could annotate the seperate fields with a version id of when they were added/updated, and if the entities version is lower than that, set that field to the new version. The same goes for fields that don't exist. Any other ways?
Having a version field makes it significantly easier in terms of updating. The easiest way in regards to updating a config file is basically have a file that tells you in a list what needs removed and what needs added
You can store such files in the db. For mysql this is a blob not sure for mongo
So you could use dash to signify its a removal line and plus that something needs added. And then put after those symbols the thing being removed or added.
Alright man, thank you for the idea 💜
I dont get this... If you have an object with default values then the entity should just merge existing properties and discard fields which arent present in the class. What would be the purpose of a Version field/annotation?
not nuking data but rather converting it?
how check if player puts on/takes off armor
what the event
i was not find something similar
i see
Paper api has that
don't call me draco malfoy!
is there any way I can declare a function in my parent build.gradle.kts and call them in subproject's build.gradle.kts files?
not really
wow that sucks
declare them in the build logic composite project
I need this in several subprojects:
fun getTestServerDir(): File {
val testServerPath = providers.gradleProperty("testserver.path").orNull
?: error("Path to test server not set! Set gradle property testserver.path to the path of your test server (e.g. -Ptestserver.path=/Users/mfnalex/mctest or using gradle.properties in your home directory: https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties)")
val testServerDir = File(testServerPath)
if (!testServerDir.isDirectory) {
error("Path to test server does not exist or is not a directory: $testServerPath")
}
return testServerDir
}
So how would I be able to use this in different places?
nah I just want to copy the files
I refuse to believe that it's not possible to simply declare a method and reuse it elsewhere
Well it’s an interesting dilemma
idk, how else would I share common things in build files if I cannot just declare a public property or function
Is there not a global gradle config or something
sure, one can set properties, but I want to be able to run some tiny arbitrary code instead of just getting the property
Oh per project
And yeah but I thought maybe you could define code in the config
Since gradle loves everything being code
Totally reproducible
I was able to make it work like this:
- buildSrc/src/main/kotlin/TestServerDirectory.kt
import org.gradle.api.Plugin
import org.gradle.api.Project
open class TestServerDirectoryExtension {
fun printTestServerDirectory() {
println("Hello from myCustomFunction!")
}
}
class TestServerDirectory : Plugin<Project> {
companion object {
const val PLUGIN_ID = "test-server-directory"
}
override fun apply(project: Project) {
project.extensions.create("testServerDirectory", TestServerDirectoryExtension::class.java)
}
}
- build.gradle.kts
apply<TestServerDirectory>()
project.extensions.getByType(TestServerDirectoryExtension::class.java).printTestServerDirectory()
that doesn't seem like it's the proper solution though...
ofc you can, but then it's not visible by other projects
you should be able to just, create a type and import it in build.gradle.kts files ?
wdym?
I need to access the project object to get gradleProperties
exTenSion fUnCtioNs
open class TestServerDirectoryExtension(val project: Project) {
fun getTestServerDirectory(): File {
val testServerPath = project.providers.gradleProperty("testserver.path").orNull
?: error("Path to test server not set! Set gradle property testserver.path to the path of your test server (e.g. -Ptestserver.path=/Users/mfnalex/mctest or using gradle.properties in your home directory: https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties)")
val testServerDir = File(testServerPath)
if (!testServerDir.isDirectory) {
error("Path to test server does not exist or is not a directory: $testServerPath")
}
return testServerDir
}
}
class TestServerDirectory : Plugin<Project> {
companion object {
const val PLUGIN_ID = "test-server-directory"
}
override fun apply(project: Project) {
project.extensions.create("testServerDirectory", TestServerDirectoryExtension::class.java)
}
}
this is my method, getTestServerDirectory()
no clue how else I would use it besides this weird extensions way
literally just like
buildSrc/src/main/kotlin/TestServerConfig.kt
fun Project.getTestServerDirectory() {
providers.gradlePropert.......
}
Weren't you talking about them like, yesterday 
wtf
its an extension function
define them top level
you don't need the entire class garbage around it
cat buildSrc/src/main/kotlin/TestServerConfig.kt
File: buildSrc/src/main/kotlin/TestServerConfig.kt
import org.gradle.api.Project
import java.io.File
fun Project.testServerDirectory(): File {
val testServerPath = providers.gradleProperty("testserver.path").orNull
?: error("Path to test server not set! Set gradle property testserver.path to the path of your test server (e.g. -Ptestserver.path=/Users/mfnalex/mctest or using gradle.properties in your home directory: https://docs.gradle.org/current/userguide/build_environmen
t.html#sec:gradle_configuration_properties)")
val testServerDir = File(testServerPath)
if (!testServerDir.isDirectory) {
error("Path to test server does not exist or is not a directory: $testServerPath")
}
return testServerDir
}
xDD
reload gradle I guess ?
alex
interesting, works for me ™️
it's wednesday
you usually answer them
not on wednesdays
damn
whats your buildSrc build.gradle.kts
if you check my history, you'll see that I always have questions on wednesdays
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
gradlePluginPortal()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20")
implementation("com.github.johnrengelman:shadow:8.1.1")
}
Interesting, smack implementation(gradleApi()) I guess ?
at least das how I learned it
is this on github somewhere
this is the version still using my extensions workaround https://github.com/SpigotBasics/basics/tree/gradle-copy-to-testserver
I'll try adding gradleApi()
lmao deleted the gradle cache, now it does find the extension function :X
welp
I was trying this for like half an hour
that's the IJ default gitignore

probably it wants to upload itself lol
it does add some subfolders though
like .idea/libraries
thx @eternal night , now I got this thing working without those stupid extensions.
I wonder though if what I'm doing here is a good idea. My goal are 4 tasks:
- in plugin: copyPluginToTestServer -> copies the plugin . jar to the test server
- in each module: copy{name}ModuleToTestServer -> copies this one module to the test server
- in modules: copyAllModulesToTestServer -> depends on all #2 tasks
- in parent: copyAllToTestServer -> depends on #1 and #3 task
Instead of a Copy task for #2, I have extended the Copy task class, so I can just identify them by that class for #3
Is that a good idea or is there a better way? Here's the full project with the current build scripts https://github.com/SpigotBasics/basics
ehh
I'd say usually you'd want to just hardcode the dependency
there is typesafe project accessors out there anyway. I think still in preview but
tho I guess yea, you can "use" the type system like that
well I need to collect all modules, I don't really want to hardcode them tbh
I thought I found a smart solution by extending Copy lol
Yea idk, at that point you'd usually just be back to extensions xD
weird, I never saw it
can I read console input in a gradle task or is that a bad idea for whatever reason?
it's not recommended at the very least
But I have heard of at least one plugin that does that
basically I wanna do sth like gradle init or mvn archetype:generate where it asks for module name and stuff
unfortunately System.console() is always null :/
I mean at the worst you could do it via system props but that is not great
I basically did it like here https://wjw465150.github.io/blog/Gradle/my_data/Gradle_Goodness/Get_User_Input_Values_From_Console.htm but for me console is always null, both from git bash and within IJ :<
ehhh, gradle daemon and console input are not great friends
but how does gradle init do it then
I also tried using --no-daemon, still no console
really?
let me try
Smack it in a Scanner and off you go
gradle init is a method in the wrapper
and that ^
lol this was easier as expected, thanks
fun readInput(text: String): String? {
print("$text: ")
return readlnOrNull()
}
If I'm going to send a Title and a SubTitle to the player, does it have to be done together in "player.sendTitle" if it's to be at the same time?
I don't think it has to
It seems that one disappears when I create a new one
just set the argument you don't want to null
Show your code
.
okey 🙂
Does anyone know in which class the server netty pipeline is located at?
The variable
ServerConnectionListener#channels iirc
that's for a client, I think they meant the global one by "server pipeline"
how can I get gradle to recognize system environment variables
currently it just won't recognize stuff set in my bash rc even though the echo command yeilds the desired result
clear caches mayb
I tried didn't work
Recursive Timber Plugin leads much to be desired performance wise
yes? it's just like any other program
read the question again emily
System.getenv works just fine
but the daemon's env vars set will be only set when the daemon starts, like any and every other program, it isn't something that is read dynamically
I have an error in my code from protocollib, and at the bottom of the error, it gives these paramaters:
[17:55:31] [Server thread/ERROR]: Parameters:
net.minecraft.network.protocol.game.PacketPlayOutEntityEquipment@452d894f[
b=99
c=[(MAINHAND, 1 netherite_pickaxe)]
]
Does anyone know if System.arraycopy allows to copy from and to the same array in overlapping regions?
I basically want to shift all values of an array by 1, hence my query
Are you making a list
If the src and dest arguments refer to the same array object, then the copying is performed as if the components at positions srcPos through srcPos+length-1 were first copied to a temporary array with length components and then the contents of the temporary array were copied into positions destPos through destPos+length-1 of the destination array.
Okay yeah, I guess I should've looked into the javadocs first lol
Nah, I'm making a set
However I probably cannot use stuff like fastutil because it's my Java 6 project again
Java... 6???
Yeah
figured it out the code was faulty for loading variables
it was using System#getProperty and I didn't notice somehow
just switched to the correct System#getenv
pepelaugh
Old man 👴
https://paste.md-5.net/kabobefaxi.java When you just want to damage an item 😩
ayo where is the EnumMap at
EnumMap<EquipmentThingy, Runnable> ftw
i'll EnumMap you
what is jishuna an enum of
all individuals with the discord name Jishuna
Thanks g
Does anybody know the difference between the two?
yes
so epoll is superior but not available everywhere?
given epoll is a linux kernel call
How to load the texturepack only when entering the lobby server and then on other modes not to load it anymore?
I cant find it anywhere, where is the "dependancy" for Votifier?
like what do I type, what is it called
where is that
CrashReport
It's probably for OOMs
a what
It allocates garbage on the heap that provides a buffer in case an OOM occurs
At least that is the intention
realistically those 10 MiB won't do much though
where can I get the MinecraftServer variable instance from?
doesn't it have a static accessor
nope
Otherwise I think you can cast Bukkit's server to MinecraftServer but do not quote me on that
What is this check forrr
during testing it isn't
People like geolykt overwriting the bukkit server instance
Double is one of the ways to save a number
Yes, I did that once. No, it did not work thanks to this method
or rather, allocate it in memory
What value do I have to pass to a GameProfile in the ClientBoundPlayerInfoPacket for changing a player's skin? Should it be the link or what?
double is a double-precision floating point number
show code
integer is a fixed point number
So while double can represent 2.4, integer can not. You either cast (round) your double to an int, or you do it some other way
Actually not even fixed point, it has nothing after the comma
uhhh
I am extremely sure you should not be using Beans with your knowledge
Okay yeah, I'd just drop whatever you are doing and go about it some other way
meh, those are just caused by dependencies that are missing
and why ist the comment in polish?
yeah but
it's decently crucial
ChatGPT won't aid you much either after some point
Don't. Easy as that. Fixing that issue will cause another issue to crop up
This entire method is unusable code
So you are saying this code doesn't come from chatGPT?
in this case, uh - WHAT
You probably can just do build = (int) version
Where do you have that code from?
Is this a plugin that already exists?
Or is this exclusively chatGPT?
Because whoever wrote this took ?di too seriously
?di this command
Guide to dependency injection: https://www.spigotmc.org/wiki/using-dependency-injection/
I'd assert that this is not how most plugins are written. With most I mean like all except a handful
?learnjava And also learn dependency management. BeanFactory looks to be a spring-specific thing. I'd say you messed up the prompt which is why ChatGPT is writing a Spring plugin rather than a bukkit plugin
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.
Though even in the context of spring it does not make any sense given that BeanFactory is an interface
Because I googled it?
It's an interface
declaration: package: org.springframework.beans.factory, interface: BeanFactory
wat
I really wish ignoring on discord would work like ignoring on IRC
what are you talking about
it's safe to presume anything to do with beans is spring
your code is all underlined red, so instantiating that type is probably wrong too
I just love to entertain random individuals on the internet
You are lucky this isn't papermc, you'd be gone pretty soon over there
Since when did #general leak into #help-development
Go back there. People there at least appreciate your work. Anyways, time to code some more Java 6 code
Your mom
PrepareItemCraftEvent#isRepair() seems to always return false, can anyone else confirm
lol, they got banned anyways. Though apparently due to a statement in #general rather than a statement on here
Yeah. regardless, good riddance
geol, what is it about java 6
At this point it is just a meme
Tbh the entire project is a meme - who in the right mind would reimplement Mixins if they could just fork it?
The funny thing is, I still use sponge alongside micromixins - in fact the micromixins impl is just in an experimental branch
repairing in this context is crafting two broken items together, is that what you're checking?
When will we have a java 2 coding experience
i mean im literally just checking isRepair()
checking if the grid contains two identical tools is the workaround im using
Java 5 is the lowest version you'll see in a minecraft context. Technically people want me to port the library to Java 5 because of that but they can do that themselves ig.
Are people trying to mixin minecraft alpha
Lmao
Apparently, yes.
Damn
But I think that project got a little bit forgotten since people only use a fabric variant or other more appropriate modloaders
How to check resource loaded status?
what exactly do you mean with that? Do you refer to resource packs or?
I'm currently developing a plugin with multi-version support that is capable of handling fake player entities. I just noticed that in the newest version (1.20.4, NMS 1_20_R3) the "connection" field in the "connection" field of a ServerPlayer object has been made protected.
Or in code:
((CraftPlayer) player).getHandle().connection.connection instanceof FakePlayerChannel
This worked fine on all 1.20.x versions but just got broken in 1.20.4, Is there any workaround to this?
protected final Connection connection;
The field has been made protected only in 1_20_R3
Just one question why are you doing .connection two times?
Are you using some library or what? I've never seen such class in nms.
The first .connection gets the ServerGamePacketListenerImpl of the ServerPlayer.
I then need to get the Connection class from that as that's the class I'm injecting in the fake players.
I guess you've never used Mojang mappings
You are wrong
The FakePlayerChannel is a custom class yes
YANPCP
because everyone wants to DIY rather than use an API
It's not a NPC plugin
you're making npcs
Do you really need this to manage NPCs? .connection.connection
yes
I've never used this thing and still created them successfully
You Always Need PCP?
Seems like a weird thing to promose, Emily
But if it's what you recommend
absolutely
That's actually how you get through each day. It makes sense
I can't really see why you are using this. Maybe I don't know enough, but I can't imagine any functionalities that wouldn't work in the way I used them.
It's meant to be an undetectable spoofer that is capable of producing fake entities. Existing solutions did not allow me to add the features I needed
A spoofer that basically inflates your player count with fake entities
not shady at all
Okay so you can do the same thing or am I wrong here
undetectable?
I mean it's not really shady, it's just adding fake players to a server to make it seem like there are more players online then there are. My question still remains though, is there any specific reason why the field was made protected in 1_20_R3 and is there a workaround?
Well the problem with that is that you still need to have chat "be alive" after a certain threshold
It's deceptive for the exact reason it works in the first place
I've never tried doing something like this before, but just one question. Why do you need this?
you sound just like cleverbot
ÖÖööö what
It's a highly popular plugin type in the skyblock and prisons community
Is it actually only for the server list?
Or do you display other players on the server too?
No we disable the actual player on the server as well. To make it "undetectable"
I'd really just need to know why the field has been made protected and if there's any workaround to it
workaround would be reflection
Well it was actually funny that it was even a thing.
Though I do wonder how this would look like in the not-so-far-future
I'd not be surprised if reflection and stuff got disabled thanks to JPMS
i mean
Broo I just imagined how it would look like a server full of bots with chatGPT api. That would be the perfect prison server.
anything in the unnamed module will behave as it always has before jpms
That's something that's actually being offered by a few of our competitors.
🤣
😛
Sadly you can't make bots pay you money
Yeah, but what happens once spigot does add a module-info?
Some would say that would never happen - others say that is the best thing ever
In the greater java community the latter opinion seems to be the most popular one
22:07:41.781: [Kore-Recoded] git -c credential.helper= -c core.quotepath=false -c log.showSignature=false push --progress --porcelain origin refs/heads/main:main
error: dst refspec main matches more than one
error: failed to push some refs to 'https://github.com/GhostAndry/Kore-Recoded.git'
when i try to push from intellij it gave me this. some can help me to fix it?
singleplayer shenanigans
it's the server's src
which also exists in the client
when you open a singleplayer world it'll spin an integrated server that also uses netty, but it's an in-memory channel, a queue of packets, rather than consuming actual networking resources
said channel is put in that list, and then if you want to click that "open to lan", it'll use an actual network channel, bind to a port etc, and also put it in that list
that mechanism obviously does not exist in the dedicated server, so the list will always contain one element
but in the client it can contain 1 until you open the level to the LAN, then it'll have 2 serverchannels
or, futures
because having shared common logic is good
there are no non-trivial downsides to that approach and it works well
I guess makes sense
where are the docs?
Hello i try to open a lvl 30 enchanting inventory , i made this it is working the enchants are the same as the lvl 30 , but one problem i am just changing the level cost so the text is still "Sharpness 1" (the lowest for each enchantment). How can i reproduce a lvl 30 enchanting table ? I know that there is offer#setEnchantmentLevel() but it will not reproduce the real lvl 30 one ``` for(EnchantmentOffer offer : e.getOffers()){
if(offer == null) continue;
offer.setCost(30);
}```
how are you making the inventory?
Wait why is level 30 enchanting suddenly = op enchantments
Cause it's like 6x the normal?
Pretty sure a sharpness 30 would kill everything instantly without other scaling
Enchanting cost, not enchantment level :p
Well technically the cost is only 3
its ok , finally i think i have to look at how they simulate random offers and replicate it
Buddy. Maybe have less to drink
He’s trying
POV: the slime is wasted
It's 10am :<
It’s 5pm somewhere
Good ole CST is getting hammered rn
What is the CST
here 00:38
The best Central Standard Timezone on earth
How many are there
1
🤔
how could I get some data from one of my class in to another one, more of I want to create custom placeholder that will show int from one of my class
?di
Guide to dependency injection: https://www.spigotmc.org/wiki/using-dependency-injection/
thanks
Guys should I make my own event handler system or listener system if the bukkit event system doesn't have enough priorities
Since forever?
I mean it's basically the last priority
Don’t modify the event in it
Or else
Well
there's a lot of ordering that I need
and whatever 6 is probably not enough
so I might just make one that goes by numbers
If you need ordering within your plugin then just handle it yourself
With a single listener method and then a list
If you need ordering among plugins that’s another story
yeah that's probably what ima do
I think I have an idea of what ima do
if i send 4 messages after another, can there be another message sent in between(from another kind of event) or are these messages always one after another?
Yes messages can be sent inbetween async
but non async this cannot happen, right?
It shouldnt
by how I imagine it, if one event listener does something heavy, the rest of the listeners must wait
in a non async environment
Message sending can be done fully async
So there’s no guarantee
Unless you used a bundle packet
i mean
even if you use a bundle packet
if someone sends a message async while the bundle window is open, it'll sneak in
I thought the bundle packet was constructed with a list of packets
And then the start and end is handled by netty
the bundle isn't handled by netty, but that's besides the point, but if someone else is queuing a packet asynchronously while you have a packet bundle open, it will sneak into the bundle
it isn't bound to any thread or caller in particular, it's just a queue in the end
intresting...
oh no... did github change their UI? Now one has to scroll back up to see the regular menu bar at the top... (e.g. with the github logo to go the start page)
if (location.getBlock().getType() == Material.AIR){
Material blockType = Material.BARRIER;
event.getPlayer().sendBlockChange(location, blockType, (byte) 0);
}
My character should be lying down but for some reason the character is standing for everyone and the server and just for me to lie down.
Does anyone know how to make the character lie down so that there are no blocks (or for one player only)?
minecraft version 1.19.4
Did GitHub change their UI? Is it a day ending in y?
It is unlikely that you need to restrict the server from updating the player's animation to others. I'm decently sure that you just need to send the block change to everyone else as well
Since it only makes sense that only the player with spoofed block packets is the only one experiencing the spoofed block packets
oh
Yeah, can confirm
Anyone know a good way to stop a projectile from breaking on hit? Like a snowball, ender pearl, egg, etc?
what else do you want to happen with it
just let it fly in the air?
Not super important. I just need to not to break
So i can teleport it, use it for other stuffs
I plan to use it for several things
And creating a second projectile doesnt really work
you can detect when its about to hit something and then teleport it away before it does
why not
would definitely be the preferred way
Cuz I have other methods that are linked to said projectile
then link them to the new projetile
So creating a new one does nothing
that aint how it work lol
Its a timed event
just tell me what exactly you are trying to achive
so I cant change objects like that
cause what i have from you so far doesnt leave me much room to help you
Projectile hit object, bounce off object based on the config
okay
check onentitymovevent
when its about to hit
then
turn around
by
reverting velocity
There is an on entity movement listener?
What exactly does it check for?
There is no such Event
Just looked at the docs
How can I make a fake player that will like redirect all chat messages it gets into a file or something
why would you use a fake player?
you can just use the PlayerChatEvent
Nah, I need to execute commands from that fake player, I wanna get their output and making a custom command sender will only work for bukkit commands
I think I’ve seen inventory with 36 slots before, isn’t there such a thing?
A 4 row inventory?
9, 27, 54, and what else? or all that are divisible by 9 in this range
It goes up to 6 rows iirc
there should be an inv for every multiple of 9 up to 54
does someone know why this animates only sometimes
TextDisplay t = (TextDisplay) damager.getWorld().spawn(interaction.getLocation().add(0, 1, 0), TextDisplay.class);
t.setText(AdventureUtil.serialize(Component.text("-" + damage).color(TextColor.color(0xff0000))));
t.setBillboard(Display.Billboard.CENTER);
t.setAlignment(TextDisplay.TextAlignment.CENTER);
t.setBackgroundColor(Color.fromARGB(0, 0, 0, 0));
t.setInterpolationDuration(20);
Bukkit.getScheduler().runTaskLater(SillySMP.getInstance(), () -> {
Transformation transformation = t.getTransformation();
transformation.getTranslation().add(0, 1, 0);
t.setInterpolationDelay(0);
}, 20);```
displayEntity.getTransformation() returns a copy iirc
so I have to set it?
Yup, just like ItemMeta
Hi I'm new to plugin development.
This is being called twice:
`public void onPlayerInteract(PlayerInteractEvent event) {
// Check if the action is a right-click
if (event.getAction().equals(Action.RIGHT_CLICK_BLOCK)){`
Is there any reason for this that is related to this code bit here. I'm basically just clicking in the air. It calls twice that it clicks the same grass block I'm pointed at.
Any help would be appreciated.
It is being called for mainhand and offhand
?interactevent
The PlayerInteractEvent may be called once per hand. If you only want code to be executed once, you can check the result of https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/player/PlayerInteractEvent.html#getHand(), then decide functionality.
For example, only executing code if the main hand was used:
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getHand() != EquipmentSlot.HAND) { // * if the hand used is NOT the main hand:
return; // do not progress past this point |
}
// provide functionality
}
I knew there had to be a command for that!
This is the solution.
Thank you very much. That was a few hours of me trying to debug my whole program. 🙃
Next time just read the javadocs :p
alex thats mean
dont tell people to read docs
thats torture
especially for new devs
Even with this page of the docs, its not exactly bold and obvious. Although maybe it should be as it probably causes a lot of problems.
But the CafeBabe bot does a nice job of laying it out.
how can I create a "bone meal effect" programmatically? I haven't found the information I need
real grow
it's too bulky and it's hardly suitable for other plants.
scroll down.
Begginer level eror, but dont get it. How do you make a list that can extend? it generates an exception: java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 0
List<Integer> list = new ArrayList<>(40);
plugin.getLogger().info(Integer.toString(slot));
if(fusePerItem.get(player.getUniqueId())==null){
list.get(slot).equals(0);
}
like i am pretty sure i define the size for the list as 40
so why does it say its out of bounds?
looking at that you never populate the list
In 1.20, is it still possible to add a fake glow effect to an item without actually adding a new enchantment? No, I don't want to add a random enchantment and hide the enchantments using a flag. I tried using NMS to change the ench compound, but that doesn't show me any working result. Here is my code: https://paste.md-5.net/iquhuseqev.cs
40 is just the internal size, not how many elements are there
Reminds me of that NonNullList I saw in mojangs code
? how can i automate that other than putting 0's manualy
Ye, spigot clears this "invalid" tag :(
So a glow effect isn't possible anymore?
use getOrDefault
ah it doesnt exist on list
easier to just null check first
I don’t think it does
uhhhhhhhhhh
Hmmm, someone could just try to give themselves the item and see
(I can't, at work rn)
/give @s iron_sword{Enchantments:[{}]} 1
(I think they changed the enchantment tag in newer versions, hm)
just null check the result of get
Would 1 == new Integer(1) be true
thought it could work
that wont fill the list
yeahh
just because you set the size doesnt mean it has content
just null check the result of get or use autoboxing
what
get(index) == nullor int xyz = get
mean dis?
whats the point of the list if you define it right there
im getting the sense of xy and you should learn java
?learnjava
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.
?xy
uhhhhhhhh
?tryandsee
Hmmm
Hnmm
Only cause of intcache
Cause of what


Shrug
due to autoboxing it will automatically call Integer.valueOf() for you which has to do with the cache
here is an example where the cache can screw you
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(1);
System.out.println("a==b? " + (a==b));
Integer c = Integer.valueOf(1);
Integer d = Integer.valueOf(1);
System.out.println("c==d? " + (c==d));
the following output is this
a==b? false
c==d? true
May valhalla save us all
I mean ain't that crazy tbf
yes but no, how you can understand the example in why it works out that is because the first two new integer calls is really in fact this
Integer a = new Integer.valueOf(1);
reason it turns into valueOf is because we are mixing types. Primitives and objects
since we already have a valueOf explicitly stated in the code
Java will take what was cached for those and see well these look the same
and thus, now the cache starts screwing you without realizing it 😛
but now, you have been educated in this and hopefully you will be more aware of your code in mixing types 😄
