#dev-general

1 messages · Page 338 of 1

forest pecan
#

static everywhere Yellow_Heart_UwU

regal gale
#

🥲

prisma wave
#

Although that might only apply to first party types

old wyvern
#

Yes

forest pecan
#

see something that isnt static?

#

add me to it

old wyvern
#

Use extensions at use site

regal gale
#

badplugin nostalgia

ocean quartz
#

@half harness Here is an example of my "util" file, in what world would you need the Util.<stuff>?

half harness
#

oh.

forest pecan
#

whats internal

#

whats that again

surreal quarry
#

package private

#

module provate*

half harness
#

but i can't make extension functions for everything

forest pecan
#

o

#

yeah

#

i remember now

ocean quartz
obtuse gale
#

Bet

half harness
#

what-

ocean quartz
#

Any.everything

surreal quarry
#

everything is an extension function

half harness
#

what would I do for sending a message to bungee -> spigot and spigot -> bungee

#

String#send?!

#

ew

regal gale
#

What

surreal quarry
#

send(“string”)

ocean quartz
#

Player.sendBungeeMessage

stuck harbor
#

lol

surreal quarry
#

if you dont like extensions

half harness
#

not player

stuck harbor
#

wht

half harness
#

im not using Plugin Messaging

stuck harbor
#

whht

ocean quartz
#

You mean logging? I have "This message will be logged".log()

prisma wave
half harness
#

1sec

ocean quartz
surreal quarry
#

if you want

#

extension functions

forest pecan
#

thats fucking insane

#

so concise

#

lol

surreal quarry
#

“blah”.info(optional file)

prisma wave
#

ngl I prefer log(s) in this case

half harness
#

like ```kt
fun sendChatMessage(ipsToSend: Map<String, Int>, message: String) {

surreal quarry
#

wdym log(s)

#

like as the method name?

distant sun
#

bm is weird

prisma wave
half harness
prisma wave
#

As in not an extension function

#

A receiver instead

surreal quarry
prisma wave
#

Ew

ocean quartz
#

String.sendChatMessage(ipsToSend: Map<String, Int>) then "Message".sendChatMessage(mapOf(something to ip))

half harness
prisma wave
#

No

surreal quarry
#

why is that ew?. you are sending a chat message to some ips that are stored in the form of Map<String, Int>

ocean quartz
#

It's ew because it's not Java

half harness
#

also string = ip, int = port

#

ok i give up

#

u win

#

gg

stuck harbor
#

no re

half harness
#

wait

#

1 more

stuck harbor
#

no

#

I said no re

surreal quarry
#

lol

half harness
# ocean quartz It's ew because it's not Java
        fun getMapFromIpAndPorts(ips: List<String>): Map<String, Int> {
            val map = mutableMapOf<String, Int>()
            for (str in ips) {
                try {
                    map[str.split(":")[0]] = Integer.parseInt(str.split(":")[1])
                } catch (e: Exception) {}
            }
            return map
        }
```what about this?
stuck harbor
#

reeeeeeee

prisma wave
#

awful

#

Absolutely horrible

surreal quarry
#

extension property dkim

ocean quartz
#

Oh my god what is that

stuck harbor
#

that method name

ocean quartz
#

Dkim, you're not in Java

half harness
#

lol

prisma wave
#

No mutability

stuck harbor
#

jesus

surreal quarry
#

val List<String>.ipAndPorts: Map<String, Int>

half harness
half harness
half harness
surreal quarry
#

its a property from that list

half harness
#

u guys aren't telling me what to do

prisma wave
#

Or even better

surreal quarry
#

dkim you could do something like list.map probably or maybe list.associateBy. i forget the name

prisma wave
#

Make parseIpAndPort and then use .map for the list version

surreal quarry
#

instead of the mutability inside the method

prisma wave
#

^^

stuck harbor
#

ur just give it some abstract ass name and make people read the javadocs

#

;)

regal gale
#

The exception handling 🥲

surreal quarry
#

but BM what do you have against extension property here

astral quiver
half harness
#

so

#

what do i change

#

u guys are throwing things at me

astral quiver
#

with this approach with inline classes you can void logging in some cases

prisma wave
#

I might have misunderstood

ocean quartz
prisma wave
half harness
#

woah

#

wtf

#

how

#

did you just

surreal quarry
#
val List<String>.ipAndPorts: Map<String, Int>
    get() = mapNotNull { it.split(“:”).getOrNull(0) to it.split(“:”).getOrNull(0).toIntOrNull() }```
astral quiver
#

when we are doing debug log, sometimes we need alot of information and we need to proccess this information, like, mapping a values of a big list

surreal quarry
#

idk if what is sent would work even

ocean quartz
#

Yeah

surreal quarry
#

yea it does

ocean quartz
#

Don't think that'd make too much sense to be a property

prisma wave
#

Yeah properties should only be for short stuff imo

astral quiver
#

with this inline function format for logging, you avoid execunting something for just logging

half harness
#
fun List<String>.getMapFromIpAndPorts() = associateBy {
    val (ip, port) = it.split(":")
    ip to port.toInt()
}
```what does:
- associateBy do
- (ip, port) do
- ip to port.toInt() do
surreal quarry
#

think about it

#

for 30 seconds

prisma wave
#

associateBy converts a List to a Map with a given function

half harness
#

i can't

#

i can't think

obtuse gale
#

We know

prisma wave
#

(ip, port) is destructuring

#

Just syntax sugar for [0] and [1]

surreal quarry
#

associateBy will associateBy
(ip, port) de structure
port.toInt()... i believe in you

half harness
#

i know what (ip, port) do

prisma wave
#

Then why did you ask

surreal quarry
#

you asked what it did

half harness
#

but now i dont know what ip to stuff does

stuck harbor
#

"getMapFromIpAndPort" christ

half harness
#

i do now

#

because u told me

#

i think

prisma wave
#

It's for maps

surreal quarry
#

blah to blah creates a pair

distant sun
#

to is an infix for Pair.of()

half harness
#

i can't

stuck harbor
#

just call it "d" and make people look at the docs

astral quiver
#

the to creates a Pair

prisma wave
#

Constructing Pairs

half harness
#

im not on ide

#

ill be on pc in like 5 hours

prisma wave
#

Then read docs

distant sun
#

a to b = Pair.of(a, b)

astral quiver
#

associateBy requires a Pair if I recall

prisma wave
#

mhm

#

actually

#

I'm not sure it does

half harness
#

anyways

#

gtg

#

bye

#

thanks 🙂

surreal quarry
#

every time

half harness
#

ill think abt it

prisma wave
#

associateBy is for (K) -> V and making a Map<K, V>

#

You want map() and toMap()

#

I think

obtuse gale
#

@obtuse gale

ocean quartz
#

Actually associateBy wouldn't work there, it'd be associate instead

prisma wave
#

Yeah associate works too

ocean quartz
#

Associate prints {411.545.1.2=8000, 152.651.5.245=6000}
AssociateBy prints {(411.545.1.2, 8000)=411.545.1.2:8000, (152.651.5.245, 6000)=152.651.5.245:6000}

astral quiver
surreal quarry
#

doesnt that mean its going from (K) -> V into Map<V, K>

#

not (K) -> V into Map<K, V>

prisma wave
#

I cba to lookup docs

jovial warren
#

associateBy basically takes a list and associates its elements by some key

#

so you go from some List<V> to a Map<K, V>

old wyvern
#

btw bm

#

We have an issue with using let for matching

prisma wave
#

uh oh

old wyvern
#

All types would have to be a resutl type or we will need it to be an expression

jovial warren
#

associateTo does the opposite, it takes a List<K> and transforms it into a Map<K, V>

old wyvern
#

Otherwise theres no way to find invalid matches

jovial warren
#

then associate takes any List<T> and transforms it into a Map<K, V>

prisma wave
#
/** {@inheritDoc} g-g-gee I don't know Rick, isn't that a bit dangerous? */
protected final @SafeVarargs synchronized static strictfp boolean $validJava(boolean φ, Class<?>[]... wheee) throws Throwable {
    do do do do break; while (false); while (false); while (false); while (false);
    return φ |= φ &= φ |= !/**/false;
}{}{}{}{}{}{}{}{}{}{}{}{}{}{}
``` aah I found it
prisma wave
#

Hmm

#

what about just a concise match binding?

#
let result = match expression with (pattern, b)
#

Returns Some if it matched, otherwise None

#

That could be the functionality for all non exhaustive patterns

prisma wave
#

Java allows some ascii characters in identifiers I think

#

but yes it's cursed

old wyvern
prisma wave
#

ok

#

Not sure about with

#

It reads nicely, but it's a whole keyword with only one use

#

I guess we can find other places to use it too

old wyvern
#
let id = match expression := pattern
prisma wave
#

Hmm

old wyvern
#

or we can just := be the match operator

prisma wave
#

Perhaps

old wyvern
#
let id = expression := pattern
prisma wave
#

Or just as

old wyvern
#

as is currently casting

prisma wave
#

yeah ik

#

But match expression as pattern would work too

old wyvern
#

yea that sounds good

#

Something like bind would be cool to pipe further things on the result

prisma wave
#

yeah

#

Tbh I think we should probably rework a lot of things if we want to go deeper into the functional side

#

Like when we made it, neither of us really understood FP I think

old wyvern
#

yea true

jovial warren
#

right, I gotta figure out how I want to do this now lol

#

a single entry point means I probably need to expose the loading stuff to the API

#

which sounds a bit whack

#

since a top-level function can't be abstract

surreal quarry
#

i dont think you do?

jovial warren
#

maybe I should take a different approach

surreal quarry
#

especially if its event based

jovial warren
#

either DI or single entry point, those are my thoughts

jovial warren
surreal quarry
#

just have plugins listen for a startup event as the fun main()
You can load the plugins in the backend. you shouldn’t need to expose any of it

#

hmm

jovial warren
#

I was first thinking of just having the function take a context param that's injected when the function is called, but that gets a bit whack

#

then I thought of having main call a top-level function that takes a higher order function as an argument (say PluginContext.() -> Unit for example), but that would need to call something

#

and that wouldn't really work

surreal quarry
#

i think the context could be very nicely provided via the startup event.
the developer can create a top level variable of the context or something which can be used throughout the plugin to get things like the server, descriptor, etc

jovial warren
#

that gets a bit whack though

#

also, as I said, I'm not sure about having the startup logic be event-based

#

since that just once again increases boilerplate

surreal quarry
#

i dont think it does?

old wyvern
#

Event based startup logic?

#

You mean the lifecycle?

jovial warren
#
fun main() {
    onStart(SomeEventHandler)
}
```or something to the equivalent
#

you would have to copy and paste that everywhere

old wyvern
#

eh

#

Just embed Elara

surreal quarry
#
lateinit var context: Context
fun main() = listen<StartupEvent> { event ->
    context = event.context;
    // blah
}```
jovial warren
#

yeah that looks a bit whack though tbh

#

first, you'd have to copy and paste that everywhere (unnecessary boilerplate imo)

#

second, using a lateinit var where you really shouldn't have to

old wyvern
#

Why not be a sane person and do what all frameworks do with an entry class dedicated to the plugin?

jovial warren
#

exactly what I was thinking

#

I think

surreal quarry
#

why do you copy paste that everywhere? It’s less boilerplate than a class even if you do, but you dont.

// example event listener file
fun listenToMoveEvent() = listen<MoveEvent> {
    //blah
}```
then just call `listenToMoveEvent()` in the startup event listener
jovial warren
#

if you mean ```kotlin
class MyPlugin : Plugin() {

init {
    // some initialisation stuff
}

}

surreal quarry
#

that could work too

#

i’ve suggested that but you didn’t like it because DI

jovial warren
#

I love constructor-based DI lol

surreal quarry
#

you said it had too much boilerplate when you inject the server, description, etc

jovial warren
#

that's not what I meant by that

#

I meant ```kotlin
class MyPlugin(
val server: Server,
val folder: File,
val description: PluginDescriptionFile
) : Plugin(server, folder, description)

surreal quarry
#

right. how do you avoid that?

#

i’m sure there’s a better way BM i was just writing something quick as a proof of concept

jovial warren
#

that's what I'm trying to figure out

ocean quartz
#

I mean use Koin if you feel like it'd be better

surreal quarry
#

i’m saying you avoid it with a startup event

jovial warren
surreal quarry
#

you are saying you won’t do that because its too much boilerplate

jovial warren
#

the constructor thingy is yeah

surreal quarry
#

you said startup event is too much boilerplate

jovial warren
#

true

#

also, that lateinit var is disgusting lol

ocean quartz
#

Idk Koin too much, but from the example it'd look something like

class MyPlugin : Plugin() {
  private val server: Server by inject<Server>()
}
surreal quarry
#

yes ik

prisma wave
half harness
jovial warren
#

also, boilerplate

old wyvern
#

Would using them in the parent class work?

ocean quartz
#

Btw @half harness that code I sent you will throw at least 3 errors if you don't do the pattern correctly

half harness
#

oh-

jovial warren
jovial warren
#

so I could use property-based DI in the super and then boom, no boilerplate in the impls

surreal quarry
#

dkim the error would probably be index out of bounds

prisma wave
#

ban property DI

old wyvern
#

nah but you probably shouldnt be forcing users into that

jovial warren
#

and if you say that's ew BM then you can fuck right off because I don't give a fuck

surreal quarry
#

if i remember the code

jovial warren
old wyvern
#

Using Koin

surreal quarry
#

event driven api :)

jovial warren
# prisma wave it is

not having to do property-based DI yourself by me doing it myself on the backend is probably the best way to avoid boilerplate injection here

ocean quartz
prisma wave
#

however you choose to hide it

surreal quarry
#

oh bardy. you could eliminate the lateinit var by providing the context in every place in the api. all events have it, commands have it, etc

jovial warren
#

and yet again running into the same issue

surreal quarry
#

wdym compromising the constructor

jovial warren
#
class MyCommand(private val context: PluginContext) : Command(context, name, permission, aliases)
astral quiver
#

DSL commands >

surreal quarry
#

command event fingerguns

jovial warren
#

if me using property-based DI on my end means my end users don't have to use constructor-based DI themselves then I'm willing to accept that

astral quiver
#
command("hey") {
}
jovial warren
#

I already have a DSL for Brigadier, so this would go with that

old wyvern
#

The other way would be to provide the plugin with something like a "PluginManager" and let the super constructor register itself

ocean quartz
#

Alternatively you can just do like Bukkit and have the server as a singleton 😬

old wyvern
#

and thus load whatever is needed

prisma wave
#

when are you embedding the clojure script engine

jovial warren
#

also, that's the exact thing I'm trying to avoid by dependency injecting the server

old wyvern
#

All this wouldnt be a problem if you just embed Elara actually

#

define variables and execute

#

🙂

jovial warren
#

I want to strongly encourage DI and strongly discourage singletons

#

which is why I should probably just embed Koin tbh

prisma wave
#

the bad ending

onyx loom
#

PLEASE tell me whats wrong with Krypton.getServer()

old wyvern
#

Burn in ashes

prisma wave
#

encourage good DI

#

not evil DI

astral quiver
#

tesla stock is 14% wtf

onyx loom
#

down or up

astral quiver
#

up

jovial warren
#

I mean, ```kotlin
class MyPlugin : Plugin() {

init {
    registerCommand(SomeCommandClass)
}

}

onyx loom
#

o

jovial warren
#

I don't even need to force users to use Koin

astral quiver
#

KotlinBukkitAPI will not force, but will have some extensions

jovial warren
#

win-win!

#

no boilerplate, no forcing things down people's throats

prisma wave
#

registerCommand(SomeCommandClass)

event<CommandEvent>().subscribe {
  :)
}```
jovial warren
#

even though the backend will use property-based DI, you won't have to do it yourself

prisma wave
#

why

jovial warren
#

no

astral quiver
#

subscribe 🤢

jovial warren
astral quiver
#

use Flow

jovial warren
#

suck it

astral quiver
#

SharedFlow

prisma wave
jovial warren
#

also, it's not even that bad, idk what your problem is

prisma wave
#

it is

astral quiver
prisma wave
#

no

jovial warren
#

sure, it might be, but it's a compromise I'm willing to accept for my end users

prisma wave
#

spring heavily discourages it

prisma wave
#

you're acting like proper DI is impossible

old wyvern
#
class MyPlugin : Plugin(
  "MyPlugin",
  listOf(MyCommand::class, MyOtherCommand::class),
  listOf(EventListener::class, OtherEventLister::class),
)
astral quiver
#

Spring do that, Dagger do that, Koin do that, Kodein do that

jovial warren
prisma wave
#

Spring heavily discourages it, Dagger also discourages it, Koin doesn't, which I consider a problem

jovial warren
#

as I said, I would rather me suffer than the users of this suffer

astral quiver
#

I don't do that, but all top usage DI frameworks do that

prisma wave
#

Kodein is even worse

prisma wave
#

who cares about having to override a constructor

#

big deal

astral quiver
prisma wave
#

Kodein's github only shows property based

#

if Koin supports actual constructor injection that's nice

astral quiver
#

also, KodeinAware and KoinComponent SUCK

prisma wave
#

but my other issues with it still stand

jovial warren
#

Koin makes you do all the instantiation yourself

#

that's also one thing I kinda like about Koin

#

no black magic

astral quiver
prisma wave
jovial warren
#

beautiful

astral quiver
#

This is required actually

#

in Android, it is required

old wyvern
jovial warren
#

also, even though it seems to be against the law apparently to do property injection, I still think it looks really nice

astral quiver
#

you can't instanciate a Application, Activity

old wyvern
#

You dont need koin at all

jovial warren
#

it just feels a lot cleaner

old wyvern
#

Thats pretty much equivalent to using singletons

prisma wave
#

yeah

old wyvern
#

Just waiting for Android to wipe everything clean

prisma wave
#

that's not dependency injection

old wyvern
#

mhm

astral quiver
#

well, ServiceLocator is that

old wyvern
#

Which?

astral quiver
#

using a singleton for DI

old wyvern
#

yea that not much of a great idea

astral quiver
#

In android, you can't run from property di

#

you can't create a custom constructor for Views (if you want use it in XML)

#

ou can't create a custom constructor for Activities

old wyvern
#

You dont use di in android

#

Atleast not in the same sense

#

you consider your activity to be the root element

#

And pass on dependencies to its dependencies

astral quiver
#

Application is the root element

old wyvern
#

As in from the scope of the activity dev

#

You are pretty much isolated at that stage

astral quiver
#

and for Views?

old wyvern
#

Except for maybe with sticky services

old wyvern
astral quiver
#

what do you do, how you get the dependencies?

old wyvern
#

If dynamically created just with constructor I assume?

#

If thorugh xml, pass in the properties you can

astral quiver
#

you can't pass property meaningful through xml

old wyvern
#

And if Views have access to the acitivity lifecycle probably hook into viewmodels?

old wyvern
#

Like Adapter for eg

astral quiver
#

Adapters you can instanciate

old wyvern
#

Yes and pass data through to Views

#

Like you do with recycler views

#

Or similar

astral quiver
#

With view binding ? of course

#

but, with Custom Views is not the same

old wyvern
#

Even without viewbinding?

old wyvern
astral quiver
#

Recycler View and Adapter does not create a Custom view

#

they just inflate a view

old wyvern
#

yea

astral quiver
#

is different from custom view

old wyvern
#

Whats the issue with inflating the view?

astral quiver
#

a Custom view, inflates a view, but its a custom view

#

inflates a layout*

#

is not the same

old wyvern
#

I didnt same they were the same*, i asked what would be the issue with inflating

astral quiver
#

You are questioning basically every single android application in the world

#

This is a commum use case in Android, you can't run from it

astral quiver
#

saying that "is not required to use property injection"

old wyvern
astral quiver
#

still does not understanding you are saying, there is no singletons when you use Koin in Android

old wyvern
#

What im saying is that there are work arounds to providing them in the normal sense which is seen throughout the provided API

astral quiver
#

you just startKoin on your Application class

old wyvern
astral quiver
#

the koin is bound to the Application, if the Application dies, everything dies with

old wyvern
#

Unaccounted shared state

old wyvern
#

You might not even rehit the point of "startKoin" I assume

astral quiver
#

what do you mean by "destroyed"

#

swiped away?

old wyvern
#

As in when the battery manager temporarily kills the process

#

And reopens in the same state

astral quiver
#

Application class is not destroyed so easy

#

the Application class will run again, and the startKoin will also run again

old wyvern
#

Pretty sure Application is supposed to be similar to singletons

#

There is normally no need to subclass Application. In most situations, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), include Context.getApplicationContext() as a Context argument when invoking your singleton's getInstance() method.

astral quiver
#

They are, and what is the problem with that?

old wyvern
#

I assume they follow the same lifecycle if they were to recommend that

astral quiver
#

oh, I guess I get your point

old wyvern
astral quiver
#

You mean: in any place I can find my Application class and uses my dependencies in their?

jovial warren
#

oh btw, what do you guys think about the idea of a plugin.yml like Bukkit's anyway?

astral quiver
jovial warren
#

still thinking actually whether I should just use annotations tbh

astral quiver
#

use saveInstanceState in things that matter

#

not in everything

old wyvern
#

saveInstanceState wouldnt work for the injected dependecies I assume?

astral quiver
#

I don't can't your point with losing state, this happen alot, but DI does not have anything with that

old wyvern
#

Im not saying DI has to do with it

astral quiver
#

I should not work with

old wyvern
#

Im saying relying* on DI will lead to places where a few expectations break

astral quiver
#

Koin uses Kotlin Delegate for the dependencies

old wyvern
#

Atleast in the form of injecting that way

jovial warren
#

as? superior

#

also, if that is null, you can't cast it to a nullable type btw

astral quiver
prisma wave
astral quiver
#

but, I should be a KotlinBukkitAPI instance or not find it

#

if there is some plugin with KotlinBukkitAPI name

jovial warren
#

if that returns null, you can't cast it to a nullable type, since apparently, according to Kotlin, null is not nullable lol

#

actually wait what am I reading

#

lol that confused me

astral quiver
#

getPlugin can return null

jovial warren
#

yeah ik

astral quiver
#

if the Plugin instance is not KotlinBukkitAPI, I want the cast issue

jovial warren
#

so you cast to a nullable type

astral quiver
#

but, I would use a better error message to do that

jovial warren
#

anyway, what do you guys think of me using a plugin.yml btw?

astral quiver
#

No, do it like Sponge does

jovial warren
#

with a thingy thingy?

#

annotation

#

that's the one

astral quiver
#

yes

jovial warren
#

also, if I was going to use annotations, I could literally remove the use for any whacky loading logic anyway I swear

astral quiver
#

Or does not do that

#

maybe plugin.yml would better

#

for CI/CD propose

jovial warren
#

yeah the annotations get a bit whack with a lot of dependencies and big info text

jovial warren
astral quiver
#

like: publish with a commit version

jovial warren
#

also, should I do a Bukkit and require a main entry in the plugin.yml

#

I mean, the only other option I really have is classpath scanning I guess

#

which would be fucking slow to do at runtime

#

right, main it is then

astral quiver
#

Release it with a Gradle Plugin, needing to write a plugin.yml sucks

jovial warren
#

guess I could take the project name and version and use those to generate a plugin.yml?

obtuse gale
#

Don't use yml

#

Ew

jovial warren
#

or maybe just ```gradle
plugins {
id 'org.kryptonmc.plugin-config' version '1.0'
}

group 'me.lucko'
version '1.0'

pluginConfig {

name 'LuckPerms' // defaults to project name
main 'me.lucko.luckperms.krypton.KryptonLuckPerms'
version '1.0' // defaults to project version

}

jovial warren
#

and JSON would be annoying to write

#

also, what's wrong with YAML anyway?

#

I mean, I can say that the YAML specification can be very lenient sometimes, but for the most part, I think it's really nice

#

I will support a multitude of formats for configuration

astral quiver
#

hocon

obtuse gale
#

Hocon good

astral quiver
#

TOML sucks!

prisma wave
#

korm

jovial warren
#

TOML is good for anything without nested structures

#

e.g. my current config is really clean with TOML

astral quiver
#

I can't think anything that does not have nested structures

jovial warren
#
# Krypton config version @version@ by BomBardyGamer

[server]
ip = "0.0.0.0" # The IP for the server to bind to. 0.0.0.0 means listen on all interfaces
port = 25565 # The port for the server to bind to. Defaults to 25565
online_mode = true # Whether the server is in online mode (authenticates users through Mojang)
compression_threshold = 256 # The threshold at which packets larger will be compressed (-1 to disable)

[status]
motd = "&#8000ffKrypton is a Minecraft server written in Kotlin!" # The MOTD. Supports legacy colors
max_players = 20 # The maximum amount of players the server can have (doesn't do anything yet, other than in the status)

[world]
# The name of the world folder (NOTE: you MUST use your own world, Krypton does not automatically generate worlds yet)
name = "world"
gamemode = "survival" # The default gamemode. Valid values are: 0, 1, 2, 3, survival, creative, adventure and spectator
difficulty = "normal" # The default difficulty. Valid values are:
hardcore = false
view_distance = 10
#

that is a beauty

prisma wave
#

everyone sleeping on ELON tho

jovial warren
#

maybe because ELON doesn't even exist

prisma wave
#

it does

jovial warren
prisma wave
#

try it

#

make a file

#

test.elon

#

it works!

jovial warren
#

yeah but there's no format specification doge_ahaha

prisma wave
#

i never claimed there was

astral quiver
#

HOCON is the best one

#

is simple and you can do something like Kotlin DSL ❤️

jovial warren
#

yeah it's not bad

#

right fine, HOCON it is then

#

what's the extension for it btw? .hocon?

astral quiver
#

.conf

prisma wave
#

.elr I believe

astral quiver
#

iirc

#

elr = elarg?

prisma wave
#

maybe

jovial warren
#

jesus christ

#

and I thought YAML's specification was lenient lol

#

okay this is actually quite nice

#

how do arrays work in HOCON?

#

e.g. json "authors": [ "lucko", "BomBardyGamer" ] in JSON, or ```yaml
authors:

  • lucko
  • BomBardyGamer
#

is there a way to do something like that in HOCON?

astral quiver
#

I don't like the yaml format of arrays

#

Always bug something with me

jovial warren
#

how do you do arrays in HOCON?

#

actually nvm, got it

#
authors = [
  "lucko",
  "BomBardyGamer"
]
lunar cypress
prisma wave
#

ok i will write json then

jovial warren
#
permissions {
  "luckperms.*" {
    default: false
    children: {
      "luckperms.commands.*" {
        default: false
      },
      "luckperms.something_else" {
        default: false
      }
    }
  }
}
```looks like JSON ngl
prisma wave
#

looks like korm

jovial warren
#

also starts to get a bit messy ngl

jovial warren
half harness
#

use yaml

prisma wave
#

Average Korm hater Vs average Korm enjoyer

jovial warren
#

I mean, Korm isn't actually that bad tbh

old wyvern
#

vs average Sx

prisma wave
#

🥲

#

Korm vs elon tho

#

Who would win

old wyvern
#

elon >> Korm

jovial warren
#

tbh, idk what's wrong with JSON or YAML personally

prisma wave
#

Json verbose

#

Yaml ugly

jovial warren
#

eh, maybe a bit yeah

#

but YAML is nice I think

old wyvern
half harness
#

yaml beautiful

jovial warren
#

stfu Yugi

prisma wave
old wyvern
jovial warren
#
name = "LuckPerms"
main = "me.lucko.luckperms.krypton.KryptonLuckPerms"
version = "1.0"
description = "An advanced permissions plugin"
authors = [
  "lucko",
  "BomBardyGamer"
]
dependencies = ["Vault"]

permissions {
  "luckperms.*" {
    default: false
    children: {
      "luckperms.commands.*" {
        default: false
      },
      "luckperms.shit" {
        default: false
      }
    }
  }
}
```yeah not sure about this
#

think YAML might look better here tbh

prisma wave
hot hull
#

toml.

jovial warren
hot hull
#

or just properties file fingerguns

astral quiver
jovial warren
astral quiver
#

Use HOCON already

#

Sponge does use it

prisma wave
#

Yaml sucks ass

astral quiver
#

Is the best one for config

#

even Ktor use it

prisma wave
#

Devops is obsessed with it for some reason

#

"The more yaml you use, the more devops it is"

jovial warren
#
name = "LuckPerms"
main = "me.lucko.luckperms.krypton.KryptonLuckPerms"
version = "1.0"
description = "An advanced permissions plugin"
authors = [
  "lucko",
  "BomBardyGamer"
]
dependencies = ["Vault"]

[permissions]
[permissions."luckperms.*"]
default = false
[permissions."luckperms.*".children]
[permissions."luckperms.*".children."luckperms.commands.*"]
default = false
[permissions."luckperms.*".children."luckperms.shit"]
default = false
```... yeah...
#

or something like that

jovial warren
half harness
#

yml is best

#

cleanest

jovial warren
#

if TOML forced the use of indentation instead of some whacky . inheritance shit then it would be better imo

prisma wave
# half harness cleanest

Until you try copy paste an indented section and have to spend 20 minutes removing all of the broken spacing

astral quiver
#

oh, HOCON supports .

half harness
#

ez

astral quiver
#

like, both is the same:

plugin.someconfig.value = 30

plugin {
  someconfig {
    value = 30
  }
}
jovial warren
#
permissions {
  "luckperms.*" {
    default: false
    children: {
      "luckperms.commands.*".default = false,
      "luckperms.shit".default = false
    }
  }
}
```okay yeah that's actually pretty cool
#

not clean, but cool

#

also no one question the second child of luckperms.* please xD

lunar cypress
#

yaml is cool until you set country: norway and your program dies

half harness
#

wot

prisma wave
#

lol what

jovial warren
lunar cypress
#

sorry, yeah

jovial warren
#

not even kidding that's actually a thing that happened once

#

a company was setting locales, and they set the locale as NO for norway

lunar cypress
#

its v funny

jovial warren
#

now, YAML's specification is so lenient that it will interpret the unquoted value NO to literally mean no, a.k.a false

onyx loom
#

💀

jovial warren
#

and PyYAML somehow also followed that

half harness
#

u have to do 'NO'

jovial warren
#

nah no shit sherlock

half harness
jovial warren
#

right, anyway, what do we think of ```
name = "LuckPerms"
main = "me.lucko.luckperms.krypton.KryptonLuckPerms"
version = "1.0"
description = "An advanced permissions plugin"
authors = [
"lucko",
"BomBardyGamer"
]
dependencies = ["Vault"]

permissions {
"luckperms." {
default: false
children: {
"luckperms.commands.
" {
default = false
},
"luckperms.shit" {
default = false
}
}
}
}

#

it's basically Bukkit minus the useless crap

#

a.k.a database, load, the single author string, website, prefix, and commands

#

the things you don't need

half harness
#

all my plugins use author string

#

😤

jovial warren
#

load is going because there isn't two loading states like there is in Bukkit

half harness
#

what is prefix?

jovial warren
#

prefix changes the logger name

half harness
#

what is database?

jovial warren
#

e.g. ```
2021-03-09 18:19 - [MyPlugin] hello there!

jovial warren
half harness
#

oh

#

whats it do?

jovial warren
#

it's basically what happens when Bukkit tries to make an ORM for accessing SQL databases

#

and that went as well as you could expect

half harness
#

Using MySQL increases chances of server crashes unless the database is hosted externally. Your server(s) can crash from reaching maximum HDD space allocated to your server.

#

epic

jovial warren
#

as I said, useless feature that should've been removed years ago

#

since we've moved out of the time where databases were a pain to get hold of or run yourself

#

oh btw, does HOCON by any chance support optional lists?

#

because that would be perfect for the authors lol

#

e.g. you can either have it be a string (single element), or a list (multiple elements)

#

probably not, but idk lol

#

also, should I support all the default values Bukkit does for permissions btw?

#

or should that just be a boolean

#

I mean, do I really need default states like op and notop?

#

they seem pretty useless tbh

frigid badge
#

forget bukkit

jovial warren
#

right then, boolean it is

prisma wave
stuck harbor
#

forget bukkit, use cljukkit

jovial warren
#

also, kinda considering your method now BM

#

but ```kotlin
class MyPlugin(
override val server: Server,
override val folder: File,
override val description: PluginDescriptionFile,
override val logger: Logger
) : Plugin(server, folder, description, logger)

jovial warren
#

don't you think that is a bit much though BM?

prisma wave
#

Looks suspiciously similar to bukkit

jovial warren
#

maybe because this is kinda based off of Bukkit because this is the part of Bukkit I like?

stuck harbor
#

but

#

thats IP theft

jovial warren
#

the Command stuff is based off of Bungee's command system because I love that too

prisma wave
#

if you pass it into the constructor it doesn't need to be an overridden val

half harness
#

Bukkkit.getServer

jovial warren
#

dkim leave

half harness
#

wHy

#

WhY

#

whY

jovial warren
#
  1. singleton
  2. get in Kotlin big ew
half harness
#

whats the

#

o

prisma wave
#

bukkit::server.ban(dkim)

half harness
#

;-;

#

bukkit::server::ban(bristermitten)

jovial warren
#

Krypton.getServer() 🤮

old wyvern
#

Screw it, run them as separate applications and make them communicate over sockets

oak raft
#

what would happen if I try and change a final variable 👀

prisma wave
#

Try and see

half harness
jovial warren
half harness
#

wot

oak raft
#

are you sure? 👀

prisma wave
#

yes

jovial warren
old wyvern
oak raft
#

k I'll try it myself and prove you all wrong 👀

half harness
#

intellij wont let u compile

prisma wave
#

javac

jovial warren
#

fuck you too Dyno

half harness
prisma wave
#

Eclipse would probably compile it

old wyvern
#

Look into "A Brief History of Time", every time you reassign a final variable, the world ends

half harness
#

wrong image

old wyvern
#

And a new one begins

half harness
old wyvern
#

Where the variable is once again final

jovial warren
# half harness eclipse

I will drive you out of this server with pitch fork in hand if you ever mention that word again

old wyvern
#

Enforced immutability

prisma wave
#

ok but let mut 🥰

old wyvern
#

The universe crashes

jovial warren
#

let mut > let

prisma wave
#

wrong

#

objectively

jovial warren
#

actually I can't agree with that anyway, since I use val more than var in Kotlin lol

old wyvern
#

We should work on rewriting specs and maybe improving some of the earlier idea tbf

prisma wave
#

yes

old wyvern
#

I do feel like we missed a lot of aspects

prisma wave
#

Yeah I agree

#

Having to use parentheses is kinda painful now I'm used to F# and Haskell

#

although that's a small issue lol

old wyvern
#

Yea we can remove that

jovial warren
#

right, so ```kotlin
class MyPlugin(server: Server, folder: File, description: PluginDescriptionFile, logger: Logger) : Plugin(server, folder, description, logger)

#

bit long that

old wyvern
#

Im starting to prefer that over ther braces

#

and parens

prisma wave
#

Maybe optional braces

jovial warren
#

actually true

prisma wave
#

Or indentation

jovial warren
#

maybe I should just wrap those into a single PluginContext class or something

#

problem solved

prisma wave
#

Elara 2 preview

let factorial n = match n
    1 => 1
    _ => n * fact ( n - 1 )
onyx loom
#

omg

jovial warren
#
class MyPlugin(context: PluginContext) : Plugin(context) {

    init {
        context.server.sendMessage(Component.text("Hello World!")) // yes, Server extends ForwardingAudience so we can do this lol
    }
}
#

now that's concise

half harness
#

will u have a Server#pluginManager#getPlugin("LuckPerms")?

#

🙂

ocean quartz
#

Hope not

half harness
#

y

#

i thought its good

#

prevents static

#

yk

half harness
#

-_-

jovial warren
#

okay, a few things wrong with that

#

actually mainly just one

half harness
#

what

jovial warren
#

property access syntax exists

half harness
#

what is that

surreal quarry
#

lol

half harness
#

;-;

jovial warren
#

plugins["LuckPerms"] instead of getPlugin("LuckPerms") smh

surreal quarry
#

blah.blah instead of blah.getBlah

#

that too

old wyvern
jovial warren
#

context.server.pluginManager.plugins["LuckPerms"] (dw, plugins will be immutable lol, no enabling and disabling other plugins without pain)

old wyvern
#

Best of both worlds

prisma wave
#

kotliners will see one syntax sugar feature and decide that it should be used literally everywhere

prisma wave
onyx loom
#

plugman for krypton when

prisma wave
#

If you look in #suggestions

ocean quartz
#

Also bardy how are you going to do things like plugin.yml?

prisma wave
jovial warren
#

after some convincing from Souza, we're using HOCON

prisma wave
#

permissions section is redundant and sucks

astral quiver
#

🥳

ocean quartz
#

Yikes, i think that's pretty meh
I think a plugin annotation sounds better

jovial warren
#

it's basically Bukkit without the crap

surreal quarry
#

permissions section gross

#

and annotations are great

jovial warren
prisma wave
#

what

astral quiver
prisma wave
#

How is an annotation not compatible with CI

astral quiver
#

Change code in compilation is not a good idea and is not that easy

ocean quartz
#

That's fair

prisma wave
#

Why would you need to change it tho?

astral quiver
#

For example versioning using currently Commit hash

#

But I'm was thinking @jovial warren , versioning I think should have on a file, but main class I don't think so

prisma wave
#

Aah good point

astral quiver
#

I think it is not required at all

jovial warren
#

also, ```kotlin
@Plugin("luckperms", "LuckPerms", "1.0", arrayOf(@Dependency("vault")), "An advanced permissions plugin", authors = ["lucko", "BomBardyGamer"])

jovial warren
jovial warren
#

that sounds like the sensible thing

onyx loom
#

still messy with indentation

jovial warren
#

^

prisma wave
#

You can use [] instead of arrayOf, you why are you repeating "luckperms" twice

onyx loom
#

lol i thought that too

obtuse gale
#

vault

jovial warren
#

one is id, the other is name

#

just what I copied from Sponge

#

id is what you use to depend on it

#

name is its name

onyx loom
#

ew

prisma wave
#

ew

jovial warren
#

idfk, Sponge

onyx loom
#

SPINGE

jovial warren
#

also, Velocity does that too

#

an id and a name

half harness
#

confusing

jovial warren
prisma wave
#
@Plugin(
  name = "LuckPerms", 
  version = "1.0", 
  dependencies = [@Dependency("vault")], 
  description = "An advanced permissions plugin", 
  authors = ["lucko", "BomBardyGamer"])
half harness
#

._.

jovial warren
prisma wave
#

tf is up with that highlighting

jovial warren
#

actually that's not bad

jovial warren
#

it gets confused

prisma wave
#

classic javascript

jovial warren
#

also, anyone who uses a 2 space indent should be shot

prisma wave
#

a real language wouldnt

jovial warren
#

cough Adventure uses a 2 space indent lol cough

jovial warren
#

and same for 8 space

obtuse gale
#

Your face is ew

jovial warren
#

just no

half harness
#

well for coding its ew

#

but for yaml its lovely

prisma wave
#

you indent your code?

jovial warren
#

yeah

stuck harbor
#

pffft

jovial warren
#

Elara circlejerk incoming

stuck harbor
#

nah

jovial warren
#

lol

stuck harbor
#

asm circlejerk time

jovial warren
#

-_-

stuck harbor
#

that word is weird

prisma wave
#

dont be ridiculous

stuck harbor
#

circle... jerk

jovial warren
#

also, assembly has indentation

stuck harbor
#

shut

prisma wave
stuck harbor
#

mmhm

prisma wave
#

jvm bytecode "indentation" 🙂

jovial warren
#

all good languages have indentation 😎

prisma wave
#

so php is good?

stuck harbor
#

mhm php is good

#

no joke

jovial warren
#

I said all good languages have indentation, I didn't say all languages that have indentation are good

prisma wave
#

so brainfuck and jvm bytecode arent good?

#

also

#

in a "kotlin" language indentation is optional

jovial warren
#

JVM bytecode isn't exactly a "language" lol

prisma wave
#

it is

jovial warren
prisma wave
#

it has a specification

#

it describes a program

#

it runs

jovial warren
#

eh, true

onyx loom
#

jvm bytecode absolutely is

prisma wave
#

a chad language like f# makes indentation a requirement 🙂

onyx loom
#

absolutely chad language

prisma wave
#

no messy code

#

in fact it is impossible!

stuck harbor
#

rust makes bad memory impossible

prisma wave
#

meanwhile kotlin has messy "conventions" on how many spaces to use

stuck harbor
#

cause the compiler will get on ur ass at the slightest notice

jovial warren
#
abstract class Plugin(val context: PluginContext)

data class PluginContext(
    val server: Server,
    val folder: File,
    val description: PluginDescriptionFile,
    val logger: Logger
)
```is that all I need btw?
obtuse gale
#

You tell me

jovial warren
#

or does Plugin need some stuff

lunar cypress
#

no successful compilation => no runtime errors. checkmate rust doubters

astral quiver
#

tesla is 20% stock up

#

wtf

stuck harbor
#

elon needs to tweet again

prisma wave
#

what if the Bukkit class was a monad

jovial warren
#

ffs you and your fucking monads

#

also, how should I deal with command registering btw?

#

just store a command map or something?

prisma wave
#

Bukkit.return()

#

returns Bukkit<Nothing> 🙂

onyx loom
#

sexy

lunar cypress
#

what part of "a monad is an endofunctor with two natural transformations" did you not understand?

prisma wave
#

haskell noob ```hs
do
input <- readline
if condition input then return 3
return 4

#

haskell pro: hahah, bro do you even monad???

jovial warren
#

kinda thinking ```kotlin
class MyPlugin(context: PluginContext) : Plugin(context) {

init {
    registerCommand(CommandObject)
    registerCommand(command("luckperms", "", "lp") {
        sender.sendMessage(Component.text("LuckPerms version ${context.description.version} for Krypton ${context.server.info.version}"))
    })
}

}

#

for example

prisma wave
#

average monad denier: "i dont understand them. they have no purpose. they are confusing. encapsulation is overrated. 👶 "
AVERAGE monad understnader: "i am at peace with the world, the sky is a monad, i hate myself, imperative languages are devil spawn 😌 "

jovial warren
#

"the sky is a monad" doge_ahaha

#

also, pls gimme feedback

prisma wave
#

"yes, i would love to listen to a 3 hour talk on the theological implications of the binding operator, why do you ask?"

onyx loom
#

the sky is an endofunctor with two natural transformations

prisma wave
#

so true!

jovial warren
#

feedback pls

prisma wave
#

fine

#

actually

#

no

#

ew

#

implied mutability

jovial warren
#

where?

prisma wave
#

registerCommand 🙂

jovial warren
#

what's implied to be mutable?

prisma wave
#

implies theres something NASTY happening behind the scenes

#

perhaps a mutable map

jovial warren
#

well yeah ofc there's a mutable map

prisma wave
#

commandevent >

jovial warren
#

commandevent <

prisma wave
jovial warren
#

ah yeah, true

prisma wave
#

we the people have the right to register commands from Coroutines-Worker-Thread-3

lunar cypress
#

what are you gonna do?? can your "library" handle 1000 threads registering one billion commands at once??? huh???! didn't think so.

prisma wave
#

precisely!!

jovial warren
#

or something like that

#

me wants own dispatcher 🙂

prisma wave
#

can it really be called "production ready" if it doesnt function under my biased test that doesnt represent a real world scenario?

jovial warren
#

can any software really be called "production ready"?

onyx loom
#

yes

jovial warren
#

I think not

prisma wave
#

? pdm is

onyx loom
#

^^

jovial warren
onyx loom
#

pdm is literally being used by google rn

#

whats funny

obtuse gale
#

his face

jovial warren
prisma wave
#

the clever minds are working on a haskell port at the moment

jovial warren
#

lol

#

PDM doesn't really fit Haskell though does it?

prisma wave
#

sadly not

jovial warren
#

since there's not really any runtime loading stuff

#

there's no classes to load

#

lol

prisma wave
#

PDM is also incredibly impure

#

you would need a LOT of monads 🙂

jovial warren
#

wtf even is a monad

prisma wave
#

maybe even too many

prisma wave
jovial warren
prisma wave
#

one of the great mysteries of life

half harness
prisma wave
#

downloads things

half harness
#

w o t

frigid badge
#

homework folder

jovial warren
#

downloads your dependencies at runtime and injects them into classpath

prisma wave
#

mutates global state

jovial warren
#

boom

prisma wave
#

depends on external data

astral quiver
#

I don't know if a do a PR for PDM or refactor the hole thing

prisma wave
#

depends strongly on 3rd party websites

astral quiver
#

the Gradle plugin does not look so great

half harness
#

hole

prisma wave
astral quiver
#

the Currently maven own library will not be required anymore

#

I think I will try to do everything from the ground and make a PR

prisma wave
#

okay ❤️

astral quiver
#

try to use the same PDM dependencies.json structure

#

but whi maven aether, it will not required anymore

prisma wave
#

you dont need to worry about backwards compatibility too much but yeah if you could that would be nice

prisma wave
# jovial warren wtf even is a monad

In functional programming, a monad is an abstraction that allows structuring programs generically. Supporting languages may use monads to abstract away boilerplate code needed by the program logic. Monads achieve this by providing their own data type (a particular type for each type of monad), which represents a specific form of computation, along with two procedures:

One to wrap values of any basic type within the monad (yielding a monadic value);
Another to compose functions that output monadic values (called monadic functions).[1]

#

Optional in Java is technically a monad

ocean quartz
#

I have a suggestion for PDM, allow us to set a "proxy" where PDM will search the libs from to download them, instead of searching them from their own repositories

astral quiver
#

Optional sucks!

#

(from Kotlin perspective)

#

Sponge API only use this for null safety

prisma wave
#

that might already exist

#

you can already set what maven central mirror you want to use

forest pecan
#

i made my mini pdm by just constructing a url

#

lol

prisma wave
#

the rest is just dictated by your buildscript

astral quiver
#

currently PDM looks all repositories to find where the libraries to in the future (running the plugin) search directly in this repository

ocean quartz
#

What I know exists is your own host where you save that right?
My suggestion is to let users set their own
Like pdm.dependencyUrl = "https://mattstudios.me/dependencies/

prisma wave
#

hmm

forest pecan
#

well, the issue is java 16

prisma wave
#

that url would have to be a maven repository

astral quiver
#

you should have your own maven host

prisma wave
forest pecan
#

im still trying to figure out a good way

astral quiver
#

that is not a problem

forest pecan
#

fefo suggested of using a custom class loader

half harness
forest pecan
#

or what luckperms did

#

jarinjar

#

its a pretty big issue

astral quiver
#

just put repositories { maven("https://mattstudios.me/dependencies/") }

#

and you are good to go

prisma wave
forest pecan
#

yea

half harness
ocean quartz
forest pecan
#

luckperms was using it and they had to switch to jarinjar

prisma wave
astral quiver
#

well, maven repo is the best you can use