#dev-general

1 messages ยท Page 149 of 1

errant geyser
#

Tbf I did do that, just not on this version

#

whoops

jovial warren
#

is IAL actually used btw?

#

just curious lol

errant geyser
#

@split talon said he'd use it, as of rn only I use it mainly I think. Frosty was the one who originally wanted it, dunno if he actually uses it

#

ยฏ_(ใƒ„)_/ยฏ

split talon
#

Iโ€™m using it ๐Ÿ™‚

errant geyser
#

o dayum

#

Well

#

IAL2.0 coming out today ๐Ÿ˜‰

split talon
#

๐Ÿ˜ฎ ๐Ÿ˜ฎ

errant geyser
#

Conclure rewrote a lot of our internal stuff so you can handle persistency a lot easier

split talon
#

I need to stop procrastinating and actually finish my project LOL

errant geyser
#

YIKES

split talon
#

Sweet. Iโ€™ll just use the update to justify my procrastination

errant geyser
#

I've just got to update the readme so you know how to use it, then I'll push it. You don't get to procrastinate for long ๐Ÿ˜œ

#

buuut I am going to update my IJ rn soo

frail glade
#

Mfw SpigotMC crashes for a second when PlaceholderAPI updates.

onyx loom
split talon
#

PAPI is too powerful to be contained by spigot

heady birch
#

JSON

#

Its jsons fault

frail glade
#

What do Jason do?

#

I'll beat him up

onyx loom
heady birch
#

Ya know

#

I really really wanna write kiteboard in kotlin

frail glade
#

Y

heady birch
#

Kotlin is just so nice

onyx loom
#

doit

heady birch
#

Yes but no

#

No one wanna use a kotlin api from java

onyx loom
#

well then they can write in kotlin fingerguns

heady birch
#

Lmao

#

Damn I wish I could just write java in rust

prisma wave
#

developers shouldn't support java anymore

frail glade
#

I mean while it might be nice, kiteboard is already so nice.

onyx loom
#

true

#

java is outdated

frail glade
#

I'd hate for that to changed

heady birch
#

Yeah

#

Buggy kotlin bugs

#

companion object virus

errant geyser
onyx loom
#

wha

#

it works for me

errant geyser
#

Also it uninstalled all my plugins and removed all my settings for some fucking reason

onyx loom
#

f

frail glade
#

You gotta update mcdev again

#

It was locking up for me

heady birch
#

I literally made a wrapper class called Colour

#

So nice though

#

Beautiful english language

errant geyser
#

Yeah AJ your fork really doesn't wanna install

hot hull
#

get gud katsu

opal ore
#

guaranteed_rewards:
enabled: true
commands:
- cr give to %player_name% VoteKey

#

wont give me keys

hot hull
errant geyser
#

Frosty

#

You're like the one other person who can't use it

hot hull
#

yet

opal ore
#

Where is #voteparty

frail glade
#

When did you buy it?

opal ore
#

yesterday

frail glade
#

Aight, I'll be home in like an hour and I'll update the database and get you access to the channel.

opal ore
#

bet

dusky drum
#

where should i get support for not being able to link acc?

static zealot
#

Jax please not. we have a spigot link system for a reason. also that's not it

steel heart
split talon
#

Ah apologies

static zealot
#

also that xD

pastel imp
#

bruv

#

I honestly don't know why but prefer the first option

#

probs cause I only see it

#

oof

static zealot
#

second one its better

pastel imp
#

YE everyone says that

#

but me not know why everyone says that

#

cause for me it's not "clean"

ocean quartz
#

First looks empty

pastel imp
#

clean

ocean quartz
#

Bland

pastel imp
#

= ?

dusky drum
hot hull
#

Very bland

heady birch
#

make a path2d out of it

#

and fill it

signal tinsel
#

Hm

#

Working on a command framework

#

Should I allow subcommands to have subcommands?

#

Like /<command> <subcommand1> <subcommand2> [arguments]

#

So like idk

#

/admin mines create [arguments]

#

or /admin crates create [arguments]

#

Just examples

hot hull
#

Have fun with that

signal tinsel
#

I have it planned out in my mind lol

#

I know exactly how it'd work

ocean quartz
#

Imo it's pretty useless since it's easily achievable with just subcommands, that's why I never added that to mine

hot hull
#

Yea again, have fun with that, it's a bish

signal tinsel
#

True

#

Though it'd be a cool addition

#

Meh I'm gonna pass for now

hot hull
#

I mean if you need subcommands for subcommands, you should really rethink your command structure GWcmeisterPeepoShrug

surreal quarry
#

just use create as one of hte arguments for the mines sub command and same with crates sub command\

signal tinsel
#

True

#

I probably wasn't gonna use it personally, but itd'be a fun addition lmaooo

surreal quarry
#
    "create" -> doSomething()
    "other" -> doSomethingElse()
}```
#

ยฏ_(ใƒ„)_/ยฏ

#

or whatever the args thing is dpeending on your command framework

ocean quartz
#

Basically the same as a subcommand of a subcommand:

@SubCommand("crate")
fun crateSet(player: Player, @Values("#crate-type") type: String?) {
    
    if (type == null) {
        sendMessage("cmd.wrong.usage", player)
        return
    }

    val lookingBlock = getLookingBlock(player)

    when (type) {
        "set" -> {
            setCrate(lookingBlock, player)
            return
        }

        "edit" -> {
            editCrate(lookingBlock, player)
            return
        }

        else -> unsetCrate(lookingBlock, player)
    }

}
signal tinsel
#

Yeah I'm building a completely new command framework

#

With a few more features

#

One of them is auto-generating help page, which is definitely handy for me

surreal quarry
#

like luckperms?

signal tinsel
#

I guess

#

Idk

#

With tab completions similar to matts

#

This is try number 2 at this framework lmao

surreal quarry
#

i was gonna try to make one

#

then i just decided to use matts cause its better than mine would be

#

lmao

signal tinsel
#

Yeah

#

I'm making my own one

ocean quartz
#

I was pretty close to not making mine, but acf's messages annoyed me a lot

signal tinsel
#

My lib is gonna be a combination of a command lib and a gui lib for rn

#

The GUI lib is done for now

#

2 features that makes mine better than matts is auto generating help and a requirements system

#

So not just permissions

versed ridge
#

What kind of requirements

#

@signal tinsel

signal tinsel
#

Like

ocean quartz
#

I think it's similar to the requirements i have on the JDA version
I was gonna add that too, but boy I procrastinate too much xD
Plus i wanna try rewriting my stuff to be more abstract

signal tinsel
#

Anything

#

Yeah its pretty much what you have on JDA

dusky drum
#

i was like thinking about making VOIP over discord for mc

signal tinsel
#

That's interesting

dusky drum
#

probably not that hard to do but i guess i will try it someday

ocean quartz
#

You know what would be cool, something similar to one of MindCrack (i think) UHC but for discord, where you can only talk/hear people if you're close to them, thought about it, but it's pretty ass to do with discord, because of how the voice channels work

dusky drum
#

i mean thats what VOIP is.

#

there is already like paid plugin on spigot for that

#

but i was thinking of making free version

ocean quartz
#

oh i didn't know what VOIP was mb

dusky drum
#

probably the easiest way to make v channel for each user and then if users are in range move them to same channel bam done

summer flax
#

hate to interject but I've had an idea... has anyone thought about making a standalone editor which allows you to put minecraft sounds and noteblock sounds together and then process it to get the code needed to play those notes? essentially a DAW for minecraft sounds and then you could put the code into a class and use it as a background music player... Dunno what you guys think. I'm not adept enough to do this kinda thing but I'll think about it as i get better just wanna know what the general opinion on this would be

surreal quarry
#

everyone would need to link discord and mc and you'd just add/delete channels like on player move or something

dusky drum
#

or if users arent together just make like waiting channel

ocean quartz
#

Yeah, but sounds pretty annoying, i wish you could control each user's volume and stuff like that

dusky drum
#

i mean you cant do that

#

but you could make ts3 module

#

toi

surreal quarry
#

isnt there an update coming out to make bots able to do a lot more

#

i doubt thats one of the things

#

but it would be cool if it was

dusky drum
#

true

#

but you'll have to verify bot for some functions

surreal quarry
#

true

#

discord shold make a way for the bot to request permission to a users account to change things like that lol

dusky drum
#

i mean they can but they probably dont want due to users that would do malicius stuff with this

surreal quarry
#

yea that could go downhill real quick

hot hull
#

Don't forget about rate limiting fingerguns_reversed

dusky drum
#

yes

#

indeed

#

i mean its free software, its good.

hot hull
#

Make your own client, ez claps

dusky drum
#

ye.

#

brb

lunar cypress
#

discord isn't free software

dusky drum
#

??

lunar cypress
#

It's proprietary

prisma wave
#

ah yes

#

The 2 definitions of "free"

dusky drum
#

okay.

hot hull
#

Bruh Johnny, shut your 4head

lunar cypress
#

well as far as I'm concerned "free software" is a term to describe open source software to which you as the end user get all the rights

#

what?

prisma wave
#

He's not wrong lol

hot hull
#

If we're discussing free, nothing on this planet is free fingerguns_reversed

#

Get gud

prisma wave
#

I mean

lunar cypress
#

uhm yes free software does exist

hot hull
#

Say hi to the fbi agent when you look at your pc cam

dusky drum
#

thats why i dont have cams

hot hull
#

Like 90% of the time a cam is useless anyways

#

Unless you've got an only fans ๐Ÿ˜

dusky drum
#

eh i use my phone as webcam ez solution

dusky drum
#

in which programing lang is barry coded?

onyx loom
#

js

dusky drum
#

interesting

errant geyser
#

Obligatory Kotlin better

dusky drum
#

typescript isnt that bad either.

errant geyser
#

Kotlin better

dusky drum
#

why is everyone so into kotlin?

onyx loom
#

because its great? ๐Ÿ™‚

dusky drum
#

i mean RS was coded in java :3

#

and its op game

errant geyser
#

Circlejerk, and it is actually a good language. The circlejerk is about to replaced with the Elara circlejerk soo

dusky drum
#

no idea which lang is that

onyx loom
#

soonโ„ข๏ธ

#

which will probably never releaseโ„ข๏ธ

dusky drum
#

lol

errant geyser
#

HEY

#

Don't trash talk Elara

#

We have a Trello board and stuff

#

And we registered sooo

dusky drum
#

lel

heady birch
#

Rust

#

All I want is graphics2d port to rust

errant geyser
#

Do it yourself fingerguns

summer flax
prisma wave
#

do the commands display the correct output?

summer flax
#

yes, the message is sent to all players and each time it shows true then false then true then false

#

so the command is working

onyx loom
#

just converted java code to kotlin code and went from 134 lines to 66 ๐Ÿ™‚

p.s nothing is braced

prisma wave
#

events registered?

#

nice

summer flax
#

yes

prisma wave
#

debug the output of getToggle() I guess

summer flax
#

my main ```java
package me.mcacutt.stophunger;

import org.bukkit.plugin.java.JavaPlugin;

public class StopHunger extends JavaPlugin {

@Override
public void onEnable() {
    this.getServer().getPluginManager().registerEvents(new EventListener(), this);
    new Commands();
}

@Override
public void onDisable() {

}

}```

prisma wave
#

ah

#

I knew it

#

2 different instances = 2 different states

#

new Commands(); this instance is different to the one in EventListener

summer flax
#

๐Ÿ‘€

prisma wave
#

so the values of the booleans are different

summer flax
#

shooot

#

okay got it

#

i know what to do

#

thank you

prisma wave
#

np

summer flax
#

no but for real, i got it now thank you

#

Clojure im starting to think i was wrong

#
public class StopHunger extends JavaPlugin {

    Commands cmds;

    @Override
    public void onEnable() {
        this.getServer().getPluginManager().registerEvents(new EventListener(), this);
        cmds = new Commands();
    }

    @Override
    public void onDisable() {
    }

    public Commands getCommands() { return this.cmds; }
}
#

i have screwed this up so badly

#
@EventHandler
    public void foodEvent(FoodLevelChangeEvent event) {
/*NPE HERE*/if (plugin.getCommands().getToggle()) {
            event.setCancelled(true);
        }
    }```
#
public class Commands implements CommandExecutor {

    private boolean toggle;
    public boolean getToggle() { return toggle; }

    public Commands() {
        Bukkit.getPluginCommand("toggle").setExecutor(this);
    }```
prisma wave
#

plugin is null

#

but you're on the right lines

#

make everything that can be final, and you'll see where the problem is

onyx loom
#

@prisma wave wanna code review

prisma wave
#

sure

onyx loom
prisma wave
#
    Player getWinner;```
that's a disturbing lack of private and a weird field name
onyx loom
#

oh yea

#

that was what clip named it and i havent changed it lmao

prisma wave
#

smh

#

other than that it's not bad

#

the class is doing a bit too much imo

#

extends PlaceholderExpansion implements Listener, Cacheable, Configurable kinda obvious SRP violation

onyx loom
#

ive a feeling i dont Cacheable

#

need

prisma wave
#

ยฏ_(ใƒ„)_/ยฏ

onyx loom
#
    public void clear() {
        winner = null;
    }```
because wouldnt papi do this for me?
prisma wave
#

you probably don't need that at all

onyx loom
#

yea

#

Configurable needs to be in this class, but should i put the event in another class thonk

#

its only an expansion anyways

#

but wanted a code review because java ew

prisma wave
#

Technically yeah it belongs in another class

onyx loom
#

did a nice clean with this expansion

#

im pretty happy

pastel imp
#

yo bois anyone already used geyser?

turbid geode
regal gale
#

Something's wrong with ProtocolLibs then

#

Or you are trying to use the server version that does not support it

obtuse gale
#

Hello, i'm wondering how you would deny an item in a vault (private player inventory)

#

nvm

wary sedge
#

test

obtuse gale
#

Yeah AJ your fork really doesn't wanna install
@errant geyser errr

#

um

#

is it just not enabling? Or is it throwing errors? Cos it could be something simple in the plugin.xml

errant geyser
#

Look at the screenshot I sent

keen creek
#

Im trying to cancel the commands that are run if they are in the config but its not working
code

@EventHandler
    public void onCommand(PlayerCommandPreprocessEvent e){
        for(String command : getConfig().getStringList("disabled-commands")) {
            if (e.getMessage().equalsIgnoreCase(command)){
                e.getPlayer().sendMessage(command + e.getMessage());
                e.setCancelled(true);
            }
        }
    }

config

disabled-commands:
 - tps
 - heal
#

wait

#

i think i got it

obtuse gale
#

why do you loop over it?

south parrot
#

^

obtuse gale
#

Why not just check .contains

keen creek
#

i tried that but it did not work, i think i found out why

south parrot
#

/

keen creek
#

yup

#

the /

#

yay it works

#

lol

#

imma change it back to contains now

hot hull
#

@quiet depot Not a fan of how you use 500 different bindings/keystraps, probs just cause I've not idea what the do fingerguns_reversed

quiet depot
#

this one collects all the commands

#

and makes a binding for it

hot hull
#

Any benefit to using your way?

quiet depot
#

srp

#

maintainability

#

extendability

hot hull
#

Imagine caring about srp :p

quiet depot
#

imagine thinking you're above srp :/

hot hull
#

Smh

keen creek
#

Why not just check .contains
@obtuse gale would this work?
if(getConfig().getStringList("disabled-commands").contains("/" + e.getMessage().toLowerCase())) {

#

wait no

#

wtf am i doing

old wyvern
#

You dont need to append the /

#

e.getMessage() includes that on command preprocess

keen creek
#

i realised that, i need to get rid of it not add it

quiet depot
#

also even if you were appending the /, it should be a character, not a string ('/')

old wyvern
#

ah ok

keen creek
#

how would i remove the /?

old wyvern
#

You want to remove it?

#

take the substring from 1-th index

keen creek
#

ok

#

just

message.substring(1);

right?

old wyvern
#

yes

keen creek
#

cool

#

i have not really done anything with substrings before

old wyvern
#

I see

keen creek
#
@EventHandler
    public void onCommand(PlayerCommandPreprocessEvent e){
        if(getConfig().getStringList("disabled-commands").contains(e.getMessage().toLowerCase().substring(1))) {
            e.getPlayer().sendMessage(Objects.requireNonNull(getConfig().getString("disabled-message")));
            e.setCancelled(true);
        }
    }

config

disabled-message: "You don't have access to this command"

#Commands to disable
disabled-commands:
  - tps
  - kill

It does not cancel the commands now

old wyvern
#

Is the listener registered?

keen creek
#

yes, it was working before, i just changed it to the contains thing

old wyvern
#

Try printing out the whole command

#

It wiill still pass through if you have "/tps <somethingElse>" or "/kill <something else>"

#

You are taking the whole command message and not the initial argument

keen creek
#

i gtg now, ill do it tomorrow

proper plaza
obtuse gale
#

whats wrong with it?

steel heart
#

Oow, you kinda have to iterate through all block in the chunk then which can be heavy I guess

obtuse gale
#

f

#

also final

steel heart
#

Certainly Iโ€™d go with storing the locations instead zits

hot hull
#

You can use typeId, it's deprecated but it's more efficient

old wyvern
#

just finished mock online written exam....

#

now that was weird af

#

I had to add another table between my laptop and where i would write

regal gale
#

sorry to whoever I just ghost-pinged..

old wyvern
#

๐Ÿ‘

regal gale
#

If you only need to check Hopper, loop through Chunk#getTileEntities(), check if it's hopper

hot hull
#

So I have some concerns when it comes to efficiency of permission checks,

[Essentials] Permissions lag notice with (GenericVaultHandler). Response took 55.197533ms. Summary: Getting group for Frcsty
Using:

fun Player.luckPermsCheck(permission: String): Boolean {
    val luckPermsAPI: LuckPerms = getProvider() ?: return false
    val user: User? = luckPermsAPI.userManager.getUser(this.uniqueId)
    if (user == null) {
        Settings.LOGGER.log(Level.WARNING, "Failed to load luckperms user data for ${this.name}!")
        return false
    }

    val contextManager = luckPermsAPI.contextManager
    val queryOptions = contextManager.getQueryOptions(user).orElse(contextManager.staticQueryOptions)

    val permissionData = user.cachedData.getPermissionData(queryOptions)
    val checkResult = permissionData.checkPermission(permission)

    return checkResult.asBoolean()
}
#

Not really sure what I can do about it to make it faster

dusky drum
#

howly how many values

heady birch
#

context manager ๐Ÿ˜

#

55ms

#

whats the logic behind getProvider

hot hull
#
private fun getProvider(): LuckPerms? {
    val registration = Bukkit.getServicesManager().getRegistration(LuckPerms::class.java)

    if (registration != null) {
        return registration.provider
    }

    Settings.LOGGER.log(Level.WARNING, "Failed to load LuckPerms API provider! (Ensure LuckPerms is properly installed!)")
    return null
}
heady birch
#

Cache that somewhere

obtuse gale
#

cant you use the elvis thingo for that?

#

nvm im dumb lol

#

I tohught that was == null

hot hull
#

Yea I gotta put it to on enable, but that can't be that slow can it?

dusky drum
#

you never know

hot hull
#

Indeed you can't

dusky drum
#

i feel like its the same speed as accessing mysql thats not on same server (latency XD)

heady birch
#

I dont think looking up a registration is particularly fast

dusky drum
#

ye

heady birch
dusky drum
#

eh still cant link my spigot ๐Ÿ˜ญ

hot hull
#

@heady birch 15ms down now that the provider is cached

heady birch
#

๐Ÿ‘

hot hull
#

Still 35ms too slow

dusky drum
#

how often do you access that permission check=?

hot hull
#

Every time a player joins/leaves

dusky drum
#

hm

#

i've noticed that to that essx randomly spams in chat that it took long time to get player permissions.

#

when someone joins

hot hull
#

Yea LP does cache it, meaning it's only the first time they join, but 40ms per player is still too slow

dusky drum
#

ye

#

maybe its just loading data from database that takes some time i guess.

hot hull
#

In Java, the bellow works, but in kotlin it doesn't, any suggestions?

player.spigot().sendMessage(TextComponent.fromLegacyText(Color.colorize(message)))
this.spigot().sendMessage(TextComponent.fromLegacyText(message.color()))
old wyvern
#

What does the IDE tell you?

hot hull
#

sec

old wyvern
#

are you in an extension function?

hot hull
#

Yea

old wyvern
#

Show me the class

#

The context matters

hot hull
#
fun Player.sendTranslatedMessage(msg: String) {
    val message = getTranslatedMessage(this, msg)

    if (Settings.HEX_USE) {
        println(message.color())
        this.spigot().sendMessage(TextComponent.fromLegacyText(message.color()))
        return
    }

    this.sendMessage(message.color())
}
old wyvern
#

hmm

hot hull
#

The entire method ^^

dusky drum
#

try basecomponent?

old wyvern
#

explode it frost

obtuse gale
#

BOOM

old wyvern
#
this.spigot().sendMessage(*TextComponent.fromLegacyText(message.color()))
``` Should work
hot hull
#

Damn another fucking *

#

Isn't exploding it slow btw?

old wyvern
#

Comparitively yes

hot hull
#

Ah okay

old wyvern
#

I assume it would possibly optimize that in this case

obtuse gale
#

what does exploding do?

hot hull
#

Makes a BOOM

old wyvern
#

converts the array into arguments for a varargs

prisma wave
#

It's for using an array in a varargs method

#

^

obtuse gale
#

ah

prisma wave
#

I believe the actual name is the spread operator

hot hull
#

I gotta remember this, cause this is the second time exploding it fixed an issue I had no clue how to fix

old wyvern
#

ah

#

I remember calling it explode somewhere

#

welp

hot hull
#

Doesn't matter, explode sounds better fingerguns_reversed

old wyvern
#

๐Ÿ˜‚

#

yea nvm explode was a function from php

#

my brain is fucked up rn

hot hull
#

com.mojang.authlib.GameProfile@55f928e8[id=<null>,name=Frcsty,properties={},legacy=false] (/**.**.**.**:**) lost connection: Disconnected

#

Aj, this is why I prefer a 1.8 client

prisma wave
#

1.8 bad Java bad

obtuse gale
#

^

old wyvern
#

km bad

hot hull
#

Kotlin good

old wyvern
#

frost what have you turned into

#

You have betrayed your kind

hot hull
#

But still, if only mojang added a reload session button in the default launcher

old wyvern
prisma wave
#

No

#

Java objectively bad

#

Can't argue with that

hot hull
#

Agreed

old wyvern
#

Lets agree to disagree

hot hull
#

Nah, let's agree to agree

old wyvern
#

nah

#

Lets agree to disagree to agree to agree

hot hull
#

FJ update today fingerguns_reversed

obtuse gale
#

fj bad

old wyvern
#

ew who even does updates

hot hull
#

Could I just async this entire thing?

fun Player.luckPermsCheck(permission: String, provider: LuckPerms?): Boolean {
    val luckPermsAPI: LuckPerms = provider ?: return false
    val user: User? = luckPermsAPI.userManager.getUser(this.uniqueId)
    if (user == null) {
        Settings.LOGGER.log(Level.WARNING, "Failed to load luckperms user data for ${this.name}!")
        return false
    }

    val contextManager = luckPermsAPI.contextManager
    val queryOptions = contextManager.getQueryOptions(user).orElse(contextManager.staticQueryOptions)

    val permissionData = user.cachedData.getPermissionData(queryOptions)
    val checkResult = permissionData.checkPermission(permission)

    return checkResult.asBoolean()
}
prisma wave
#

Yes and no

#

you could async it but then you wouldn't be able to get a result

old wyvern
#

What in the hell are you doing here xD

prisma wave
#

Unless of course you used coroutines fingerguns

old wyvern
#

but wait

#

Does luckperms register the permission into bukkit?

#

Why not just Player.hasPerm

hot hull
#

Well I mean I don't really have an option, it takes 30ms to check the perm on first join (after that it's cached),
Yugi because hasPerm doesn't account for inherited groups

old wyvern
#

ah

prisma wave
#

ouch

#

yeah try asyncing it then

old wyvern
#

Async should be fine for FJ

#

no one would care if the join message is 30ms late than the actual join

hot hull
#

Some fucker decided he wanted inheritence

old wyvern
prisma wave
#

Just do the checking in AsyncPlayerLoginEvent fingerguns

old wyvern
#

km

#

question

hot hull
#

Or ya know, do the perm check in PlayerLoginEvent, so that when PlayerJoinEvent gets triggered, you already have the result fingerguns_reversed

old wyvern
#

so the bukkit scheduler entering synchronized tasks is just the thread going through a task queue right?

prisma wave
#

synchronized tasks?

#

oh synchronous

old wyvern
#

yes

prisma wave
#

Yeah afaik the scheduler just checks what tasks should be ran and runs them every tick

old wyvern
#

I meant as in how it functions in moving from one thread to another

prisma wave
#

oh

#

It doesn't?

old wyvern
#

um I dont think I phrased the question right

#

let me give you an example

prisma wave
#

it stores the synchronous tasks in 1 collection and ticks them on the main thread, and the others are ticked by a thread pool

hot hull
#

Unless of course you used coroutines fingerguns
@prisma wave Teach me fingerguns_reversed

old wyvern
#

Async Task:
Do something
Sync Task:
run something that should be in the main thread

#

ah

prisma wave
#

I'm pretty sure that's how it works anyway

old wyvern
#

hmm, so coroutines have an implementation for main thread on android and jfx.ect

prisma wave
#

yeah

old wyvern
#

Would it be possible to create a sync dispatcher when needed?

prisma wave
#

You could make a bukkit one pretty easily

old wyvern
#

So we have move the thread to the required context

prisma wave
#

I believe so

old wyvern
#

Can you give me an example

#

Couldnt find one in the docs

prisma wave
#

I've never actually done it so not atm

#

Sx had one iirc

old wyvern
#

ah

prisma wave
#

I'll give it a try soon

#

@prisma wave Teach me fingerguns_reversed
@hot hull
20 minutes

old wyvern
#

Alrighty, also is pdm somewhat stable for use rn?

prisma wave
#

Kind of

#

It works fine for the kotlin stdlib, not much else

#

Been working on some bugfixes though

old wyvern
#

Ah thats good enough for me rn

#

I really didnt want the 2MB extra from kotlin but wanted to try it in a plugin

prisma wave
#

Ah cool

hot hull
#

I don't think I'm gonna be using pdm this update KM

prisma wave
#

Yeah it should work fine for that purpose

#

๐Ÿ˜”

hot hull
#

But next update, for sure fingerguns_reversed

prisma wave
#

What if I fix all the bugs

#

Today

old wyvern
#

Is pdm limited to spigot plugins?

hot hull
#

I'm gonna be updating in a couple hours KM, so :c

onyx loom
#

Today
@prisma wave do it

prisma wave
#

I am

hot hull
#

Also, Kali, your server is just stupid cause the converter works perfectly fine for me

prisma wave
#

@old wyvern kind of. 99% of the code is decoupled from spigot but using it outside of a plugin is a bit trickier

onyx loom
#

๐Ÿ˜ฎ

old wyvern
#

trickier as in?

prisma wave
#

you have to provide the ClassLoader yourself and things

onyx loom
#

idk what was happening frosty cry

prisma wave
#

Although, all of the unit tests are decoupled from spigot and it works fine

#

Sooo

old wyvern
#

hmm

prisma wave
#

I'll send an example 1 sec

old wyvern
#

alrighty

hot hull
#

Another question, is it worth allowing people to use like 7-8 different hex formats, or should I just stick with the one I currently have?

old wyvern
#

stick with one

heady birch
#

7-8

#

I want to know what they all are lol

onyx loom
#

when will there be a universal format for mc

hot hull
#

Probably never

heady birch
#

Whats the most dominant at the moment

#

<#>?

hot hull
#

To be honest everyone has their own format lmao

#

I use #<FFFFFF>, Gaby uses <#FFFFFF>, There's also: &{FFFFFF}, &FFFFFF

#

And a shit ton more

prisma wave
#

I prefer the Clojure style (# :FFFFFF)

hot hull
#

Best is ofc ยงxยงFยงFยงFยงFยงFยงF

prisma wave
#

hideous

pallid gale
#

&#FFFFFF

hot hull
#

So KM, coroutines

prisma wave
#

yes

#

those magical things

#

continuation passing style combined with compiler generated callbacks

#

idrk where to start

hot hull
#

Give me an example

#

Probably best way to start

prisma wave
#

alright

#

i've not actually used them much in spigot but I used them for a bot a while back

#
    override suspend fun CommandEvent.handle()
    {
        val message = awaitReply("Please wait...")

        val restPing = jda.restPing.await()

        val gatewayPing = jda.gatewayPing

        message.editMessage("""
            **Gateway Ping**: $gatewayPing ms
            **Rest Ping**: $restPing ms
        """.trimIndent()).await()
    }``` here's a very simple example

`suspend` means that the function can pause its execution (known as "suspending"). all the await functions are just wrappers for JDA stuff that signals to pause the function.
#

basically what happens is you write blocking code, and the compiler changes it into callbacks

#

but a coroutine itself is a lightweight thread (the best analogy is a BukkitTask on a much bigger scheduler)

#

so you can make thousands of coroutines and "block" all of them without suffering any performance issues

hot hull
#

,

prisma wave
#

lol

#

?

hot hull
#

eating rn, gimme 10mi

#

n

prisma wave
#

aight

#

@old wyvern here's how you use it outside of spigot ```java
classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
libraryDirectory = Files.createTempDirectory("PDM").toFile();

    pdm = new PDMBuilder()
            .rootDirectory(libraryDirectory)
            .classLoader(classLoader)
            .applicationName("PDM-Test-Suite")
            .applicationVersion("N/A")
            .build();

whereas inside spigot it's justjava
new PDMBuilder(plugin).build();

heady birch
#

๐Ÿคข

prisma wave
#

indeed

#

wait what

heady birch
#

Clever though

prisma wave
#

what's actually wrong with that

heady birch
#

(the class loader bit)

prisma wave
#

apart from being effort

#

oh yeah

#

well it needs a URLClassLoader

#

so that was the best way of doing it

heady birch
#

Pdb.getClassLoader(class)

hot hull
#

KM, how would you make your own await, instead of persay using the JDA wrapper in the above case

prisma wave
#

that wouldn't work

#

I can send you the one I used if you want

heady birch
#

โ˜น๏ธ

prisma wave
#
suspend fun <T> RestAction<T>.await(): T
{
    return suspendCoroutine { cont ->
        this.queue({ cont.resume(it) }, { cont.resumeWithException(it) })
    }
}
``` @hot hull 
ngl i'm not 100% confident on how this works, but afaik it pauses the current coroutine, then queues the RestAction, and when it finishes, it resumes the coroutine
hot hull
#

I'll play around with it, and let you know if I've got anymore questions

prisma wave
#

alright

#

i don't fully get how it works myself tbh

#

but me and yugi can probably give an ok explanation

hot hull
frigid badge
#

or me

#

but I'm lazy

heady birch
#

Afternoon

prisma wave
#

yo

onyx loom
#

greetings

prisma wave
#

WHYYY

#

it fails and then says it's already been published

onyx loom
#

aaaaaaaaaaaaaaaaa

hot hull
#

KM, do I need a dependency or something, because RestAction doesn't seem to be a thing?

prisma wave
#

that's from JDA

#

lol

hot hull
#

Ah I'm dumb fuck

prisma wave
#

i forgot you meant for plugins

regal gale
obtuse gale
#

testy thonking

hot hull
#

@prisma wave If I do use a coroutine, I'm guessing everything that calls this function should also be a suspend function?

prisma wave
#

it has to be

#

eventually you'll want to use a dispatcher though

#

to avoid having literally everything be suspend

#

the most common thing is kotlin GlobalScope.launch { someSuspendFunction() } which makes a new coroutine to run the function

#

although that's something of a bad practice

old wyvern
#

yea use the CoroutineScope function

#

also, why do they have a function with capital casing

#

๐Ÿ‘€

prisma wave
#

to make it look like a class I guess

old wyvern
#

xD welp

heady birch
#

borger

hot hull
#

Yea I'm gonna have to use the dispatcher, since I'm calling that method on an event

heady birch
#

ah the joys of kotlin

prisma wave
#

kotlin good

heady birch
#

rust gooder

old wyvern
#

๐Ÿคฆ

prisma wave
#

no

old wyvern
#

all languages good

prisma wave
#

stinky rust

#

rust gives tetanus

#

kotlin doesn't

old wyvern
#

elara good ๐Ÿ‘

prisma wave
#

coincidence? I think not

#

elara best language

old wyvern
#

๐Ÿ˜‚

heady birch
#

whats tetanus

#

oh

#

๐Ÿ˜ซ

old wyvern
#

its an infection

prisma wave
#

yeah

#

take that

hot hull
#

the most common thing is

GlobalScope.launch {
  someSuspendFunction()
}``` 
> which makes a new coroutine to run the function
Can you gimme an example?
prisma wave
#

rust user

heady birch
#

lockjaw

#

that doesnt sound nice

prisma wave
#

@hot hull that literally is an example?

old wyvern
#

xD

heady birch
#

have you ever yawned so hard and your jaw locks

#

Oh

#

Tetanus is often associated with rust, especially rusty nails.

hot hull
#

I'm so confused

old wyvern
#

Frost

#

think about it this way

heady birch
#

Additionally, the rough surface of rusty metal provides crevices for dirt containing C

#

C bad?

old wyvern
#

Anything inside a couroutine scope is switched to a CPA style by the compiler

#

So you had chained future calls in java

#

Those are now done for you when done inside the context of a coroutine scope

#

Every call to a suspend function is a chaining point or a suspending point

#

Do understand how it relates?

hot hull
#

Imma just go back to sleep fingerguns_reversed

prisma wave
#

the gradle plugins portal sucks ass

#

i've literally changed the version 4 times and it still fails to publish it

old wyvern
#

rip ๐Ÿ’€

lunar cypress
#

Does Bukkit/Spigot create a new plugin class loader for each plugin when you reload the server?

old wyvern
#

Yes

lunar cypress
#

Bummer

heady birch
#

Ya know command line args?

#

--port 25565

#

Is there like a built in parser for that in java or not really

#

guess its just key value args[0] args[1]

prisma wave
#

not that I know of

lunar cypress
#

Clojure has one fingerguns

old wyvern
prisma wave
lunar cypress
#

oh man instrumenting plugin classes is beyond horrible

#

who designed this shitty plugin system

#

i'd like to talk to bukkit's manager

chilly jungle
#

Come talk to me @lunar cypress

lunar cypress
#

are you responsible for this mess alert

chilly jungle
#

No

lunar cypress
#

good

#

have you done something like this before and have any recommendations?

#

I'm currently hacking something together but it's not a beauty

chilly jungle
#

Sometimes we have to take everything into consideration, not just looks lol

#

tbh Iโ€™d have to see what you are doing

#

Join room 1 and share

lunar cypress
#

Uh sure gimme a couple of minutes ima grab something to eat first

prisma wave
#

Ah yes, the pain of trying to do anything remotely clever inside Bukkit's classloading fuckery

lunar cypress
#

In case you've done something with custom class loading before lmk what you know

#

I just went to talk to clip like he said but all that's coming from his mic are snoring sounds lmfao

#

omg my approach actually worked

#

the only problem is

#

now the legacy material transformations aren't applied anymore

prisma wave
#

๐Ÿค”

#

that's a strange side effect

lunar cypress
#

well it's not

#

since I'm loading the classes myself

#

Do you know where the code for those transformations is located?

#

and if there are more things that happen during regular class loading

#

or does it use a java agent for this? I have absolutely no idea, can't find it

errant geyser
ocean quartz
#

What's different on that fork?

errant geyser
#

Kotlin and Gradle by default

#

Saves about 10-30 seconds per plugin/project, but its useful

ocean quartz
#

Ooh nice

errant geyser
#

Jaims how DARE you

#

And oTDan

#

Elara is LEGENDARY

ocean quartz
#

What is Elara?

surreal quarry
#

is it like your language lol

old wyvern
#

Shh

errant geyser
#

Mine, BM and Yugi's soon to be yeah

prisma wave
ocean quartz
#

Oh nice

obtuse gale
#

So what is Elara?

errant geyser
#

A language

obtuse gale
#

That I understood

errant geyser
#

Or it will be

old wyvern
#

A multi paradigmn beautiful baby

surreal quarry
#

anyways kotlin good

errant geyser
#

indeedalydoodaly

hot hull
#

@old wyvern Not enough commitment and experience in that field if you ask me

errant geyser
onyx loom
#

it do be pretty strong ๐Ÿ˜ณ

prisma wave
#

lol

lavish notch
#

How would I parse \n?

prisma wave
#

to do what?

ocean quartz
#

#development instead and Did you forget to define a modern (1.13+) api-version in your plugin.yml? it's in the error

proper plaza
#

Oh srry

lavish notch
#

@prisma wave The usual new line.

onyx loom
#

is this in a config?

lavish notch
#

Yeah

prisma wave
#

oh

#

just split over '\n'?

onyx loom
#

u dont. u get a List<String> fingerguns

lavish notch
#

Is there an easy way to apply that to all messages, or do I have to apply that to each individual message (I'm using ConfigMe)?

onyx loom
#

make a function ig

lavish notch
#

and I'm just doing config.(MSG NAME)

lunar cypress
#

Could you add a simple way to pdm to create a PluginDependencyManager with just a Class<? extends JavaPlugin> or something? It's technically possible right now but it'd be nice to have a more convenient constructor for it. It'd be useful if you have fields with external dependencies

#

@prisma wave

prisma wave
#

Hmm

#

Could you give an example?

#

How exactly would that work? Just use JavaPlugin.getPlugin?

#

Or is it purely for convenience

obtuse gale
#

@obtuse gale Henlo pls fixes boi thanky
at school rn, will try when im home

old wyvern
#
@Yugi Not enough commitment and experience in that field if you ask me```
@hot hull what were you replying to?
spiral iris
#

There's no possible way to change the default generated structures even with a plugin is there?

pastel imp
#

Hi.. wanted to ask if paper 1.16.1 is stable enough to have like 200 players +-?

remote goblet
#

if you're smart about it

#

yes

#

but then again

#

minecraft sucks

#

so maybe not

pastel imp
#

??

#

= ?

old wyvern
#

Depends on the hardware you run it on

pastel imp
#

it will either be Intel Xeon E5-1650v3 3.8 GHz*
or Intel i7-4790K @ 4GHz

#

8-10gb ram

#

depends on what you say

#

next

old wyvern
#

But compitively 1.13+ performs worse than 1.13-

pastel imp
#

which means

old wyvern
#

Thats probably not enough

#

For 200

pastel imp
#

16gb ram?

#

or you mean cpu?

onyx loom
#

that wouldnt handle 200

#

maybe on 1.8 tho

pastel imp
#

speaking about ram or cpu?

#

lol

onyx loom
#

both

pastel imp
#

oof

#

sad point is: vps are ducking expensive

#

oof

#

ok lets say 100

old wyvern
#

I have a Ryzen 7 3800X with 15gigs

pastel imp
#

(good beggining)

old wyvern
#

It works best at less than 30

#

Players

pastel imp
#

oof?

#

1.12.2?

onyx loom
#

are u expecting 200 or do u have confirmed 200 players?

old wyvern
#

1.15.2

pastel imp
#

are u expecting 200 or do u have confirmed 200 players?
@onyx loom just speaking high

#

probs wont be 200

#

just wanna do the IFs

old wyvern
#

Probably won't have a nice time handling that

pastel imp
#

oof

#

probs will have like 100

#

hopefully xd

#

also don't have high budget

#

so that kinda fucks up

obtuse gale
#

If I thenApplyAsync or whenCompleteAsync an already completed CompletableFuture, will the callbacks be called immediately after? ๐Ÿค”

south parrot
#

If I teleport an entity every 1 tick this can maybe do lag in my server?

#

Specially at tps?

#

(entity stills in the same chunk)

regal gale
#

I don't think it will lag though

hot hull
#

@old wyvern Development, making a bukkit fork from scratch

old wyvern
#

??

#

oh

hot hull
old wyvern
hot hull
#

@south parrot Depends on the entity amount, if you have hundreds, that's lag

south parrot
#

@hot hull its only an armor_stand but what about if I put another stand doing the same thing (tp every 1 tick) in another location

#

๐Ÿค”

#

These lag issues are practically thanks teleport void or the ticks that I do for teleport the entity?

#

Or is something special like chunks? OmO

hot hull
#

Can you explain the purpose of it

keen creek
#

how do i get only the first word of a string and delete all the words past the first word?

old wyvern
#

split it at " " and get the first element?

keen creek
#

ok thanks

hot hull
#

Or just use Arrays.copyOfRange

old wyvern
#

Or just use Arrays.copyOfRange
@hot hull
For one element?

#

๐Ÿ‘€

south parrot
#

Can you explain the purpose of it
@hot hull Creating an animation using armorstand, for example up and down everytime

#

but with style

#

haha

#

for that i have to teleport the entity (armorstand) every tick for complete the animation that I want

regal gale
#

You can use setVelocity for this

south parrot
#

i dont know how setVelocity works

#

so

regal gale
#

It's like pushing toward effect or smth

steel heart
#

Itโ€™s just a vector

south parrot
#

oo

#

got it

regal gale
#

Itโ€™s just a vector
@steel heart thanks, captain obvious..

steel heart
south parrot
#

what's the diff?

#

i mean, so the void of teleport that has an entity can makes the server lag?

#

or this is thanks the time of ticks that I'm executing the teleport void?

steel heart
#

Wym?

regal gale
#

What he meant was that he wanted to make an animation which the entity will move up and down constantly

#

Just use Entity#setVelocity

steel heart
#

Oh thats interesting

obtuse gale
#

Is there a fancy way to export projects with IJ or do i just copy the folder & zip it

#

this might be a dumb question lol

#

no like just to send to a friend lol

quiet depot
#

yeah just zip it

obtuse gale
#

aight

regal gale
#

Sometimes I do be stupid for a time ๐Ÿ‘€

#

For example: decompile sk- thing

obtuse gale
#

its open source?

regal gale
#

It's already os, but it was very confusing to navigate

obtuse gale
#

:what:

#

its just a github repo, how is that confusing

regal gale
obtuse gale
#

the main class is 1754 lines long

analog crater
#

What is the point of creating a new thread to just let it sleep?

regal gale
#

Don't ask me ๐Ÿ‘€

heady birch
#

Lol

tacit cave
#

hello

#

how do i make random int Item?

#

Minecraft*

hot hull
#

:what:

lunar cypress
#

How exactly would that work? Just use JavaPlugin.getPlugin?
@prisma wave no, you could use the class loader to get the required data

#

(except for the logger maybe)

prisma wave
#

oh

#

I see

#

yeah I guess I could add something for that

lunar cypress
#

this would be useful for a few of my use cases, because it allows you to do it in a static initialiser (before the fields of the class are loaded)

#

Right now, if you have a field whose type comes from some dependency or that itself declares fields from some dependencies or anything like that it will throw

#

because it's loaded before the dependency can be put into the class path

#

the downside of this: since the class loader isn't public you need reflection

prisma wave
#

It already uses reflection so that's not such a problem

#

so it would be like java class PluginClass extends JavaPlugin { static { new PluginDependencyManager(PluginClass.class).downloadAllDependencies().join(); } }?

lunar cypress
#

and (possibly) even parse the plugin.yml yourself (that I'm not too sure about, the class loader has a field as far as I'm aware but it may not exist in every version)

prisma wave
#

parse the plugin.yml for the name and version?

lunar cypress
#

yeah

prisma wave
#

that's clever

#

alright I'll make an issue

#

still waiting on gradle to be able to actually update much though :/

lunar cypress
#

I still haven't figured out how to view the source of a tag for a given spigot version so I can't tell whether it's necessary though lol

prisma wave
#

tag?

#

you mean a commit tag?

lunar cypress
#

yeah

prisma wave
#

why would that be necessary

#

unless I'm being really slow here

lunar cypress
#

to look at the differences of PluginClassLoader across different versions

prisma wave
#

oh right

#

yeah

heady birch
#

Why stupid kotlin not generate javadoc????

lunar cypress
#

to see which fields are always there

prisma wave
#

that's a potential problem, I'd rather not deal with spigot version clashes

heady birch
#

I just type /* and it do it for me in java

#

/*

#

@param

prisma wave
#

because kotlin doesn't use javadocs

#

lol

heady birch
#

I have to actually MANUALLY type params

#

๐Ÿ˜

lunar cypress
#

this shouldn't be too big of a deal

prisma wave
#

Hopefully not

lunar cypress
#

some fields it should always have, like the jar File

#

so worst case scenario you have to go from there for compatibility

prisma wave
#

Yeah even that wouldn't be so hard

heady birch
#

src/main/kotlin in maven right?

prisma wave
#

yes

#

also Ew maven

#

also bigger Ew maven with kotlin

heady birch
#

๐Ÿ™‚

prisma wave
#

That's like the worst possible combination

obtuse gale
#

ew

heady birch
#

can i convert it

obtuse gale
#

gradle init?

prisma wave
#

Yes

heady birch
#

no

#

gradle not found

#

please instruct me ๐Ÿ™‚

#

i did it with kite board and forgot how

obtuse gale
#

do you have gradle installed

heady birch
#

i dont want to tinstall it

#

i want to use it

hot hull
#

open IJ terminal and do gradle init

#

If it doesn't work, install gradle fingerguns

heady birch
#

gradle: command not found

#

No

hot hull
#

Wdym no

heady birch
#

I said I didn't want to

obtuse gale
#

you need to lol

hot hull
#

bruh

obtuse gale
#

sicne ur project doesnt have the wrapper

heady birch
#

No

#

I don't want to install it

#

It installs stupid dependencies

#

5 different versions of Open JDK I dont want

prisma wave
#

No?

heady birch
#

==> Installing dependencies for gradle: openjdk
==> Installing gradle dependency: openjdk

#

this is on a mac with home brewer

hot hull
#

What u on about?

heady birch
#

I dont want jdk14

#

ok working

prisma wave
#

why wouldn't you want openjdk

heady birch
#

How to shade kotlin with gradle

#

How do I change it to gradle file structure

#

Its still maven

#

Bump

lunar cypress
#

Tf

#

Gradle and maven file structures are identical

heady birch
#

Really?

#

Oh yeah

#

But it makes a module thingy

obtuse gale
#

w?

heady birch
#

total rubbish

#

@prisma wave Proper way of making a kotlin executable

#

Shouls I use application plugin?

prisma wave
#

Yeah

#

Same as Java

heady birch
#

error

#

Cannot assign 'String' to 'Property<String>'
Access to 'mainClass' exceeds its access rights

prisma wave
#

Use mainClass.set(blah)

#

also how are you doing the main class?

#

it's a bit different in kotlin

heady birch
#

fun main(args: Array<String>) {

#

There is a class in that file

#

But the fun is outside the class, right?

#

Worked fine with maven

#

Gradles fault

#

once again

obtuse gale
#

at least its not xml

prisma wave
#

it can't be in a class

heady birch
#

Its not

prisma wave
#

It needs to be either top level, or in an object with @JvmStatic

heady birch
#

Its underneath the class

prisma wave
#

If it's top level wouldn't it generate to ClassNameKt.class?

#

check the compiled output

heady birch
#

yeah that works

#

assumed kotlin application plugin would rewrite that

#

Now

#

Surely it will shade kotlin automatically

#

Being a kotlin project

prisma wave
#

no

heady birch
#

๐Ÿ˜

prisma wave
#

the kotlin plugin isn't responsible for shading

#

SRP

#

lol

heady birch
#

How is it done with gradle then

prisma wave
#

shadowJar

#

Or just the jar plugin

heady birch
#

Taht third party stupid thing

prisma wave
#

you can do it vanilla

#

just shadow is better

heady birch
#

No

#

KORM doesnt do it

prisma wave
#

Wat

heady birch
#

I should have stuck with maven

#

And java

prisma wave
#

why

heady birch
#

Its so stupid

prisma wave
#

what does korm have to do with anything??

heady birch
#

So you create a gradle project

#

And cant even use run kotlin

#

Without some other thing

#

Allowing you to shade kotlin

prisma wave
#

that's literally the same with maven

lunar cypress
#

Thonk

prisma wave
#

You need the shade plugin with maven

#

no?

heady birch
#

Yes but thats different

lunar cypress
#

How

prisma wave
#

it's literally 1 line to add shadow

#

quit complaining for the sake of it lol

heady birch
#

Ok maybe I am a little baised

hot hull
#

gradle is so much cleaner than maven, like damn 1 line to relocate a package, nice af

#

Where as XML = doodoo fingerguns

heady birch
#

no

obtuse gale
#

xml bad

#

prove me wrong

heady birch
#

SOAP.

obtuse gale
#

maven does need soap

heady birch
#

the prtocol :eye role:

#

inconsistent mess

#

sometimes i think life is a prank

sudden ether
#

Can anyone help me compile a gradle project? I have a few issues and I'm lost.
https://github.com/SpleefX/SpleefX is the plugin I'm trying to compile. I need to modify it.
Its missing libs that dont have repos
How do I include WorldGuardExtraFlags.jar

heady birch
#

๐Ÿ˜ฆ

hot hull
#

Smh Niall

obtuse gale
#

HMMM

heady birch
#

absolute bs

hot hull
#

So Aj, any progress with the animals?

heady birch
#

Its actually gone and broek

obtuse gale
#

nope

#

ive got no clue how to do this and make it easy to use

old wyvern
#

What animals?

#

The armorstand thingys?

hot hull
#

yes

old wyvern
#

I think I have an old project that uses those for weird mobs, ill send it if I find it

hot hull
#

I kinda don't want to see how other people did it :p

#

Makes it more of a learning experience, Aj, you got a repo made for it?

obtuse gale
#

I will in a sec

old wyvern
#

Ah fair enough

heady birch
#

Not angry

#

Dissapointed with gradle