#[MEGA THREAD] Get Your Code Reviewed or Review Others

1 messages · Page 7 of 1

hardy hedge
#

Custom colors and the ability to cast it to send script specific errors?

#

It's a separate class for a reason imo

#

That's why I did it

#

For example a lot of these are errors I throw for people making their bot script, so I want it to highlight red rather than white and I want it customizable to my liking

wintry fern
#

colored logs?

#

the server doesn't preserve colors in logs and instead logs the color codes along with whatever message

#

rather annoying sometimes, if there is anything you could do better in terms of logging is actually creating a log in your plugin directory of everything your plugin is doing 🙂

surreal peak
#

and idk what this does but have you thought about unsanitized input

#

and i dont see a reason to use a BotLogger and not a java.util.Logger

hardy hedge
surreal peak
#

why the String.valueOf

hardy hedge
#

Y'know what, I'm not sure. I ripped that off spigot forms

surreal peak
#

what does it even do

#

or what is it supposed to do

hardy hedge
#

It's supposed to strip the ampersand color codes

#

Actually no I didn't rip this from spigot forms sorry I just went into source code on how they did ChatColor#stripColors() and replaced the § with &

hardy hedge
hardy hedge
surreal peak
#

i mean what is the script engine supposed to do

hardy hedge
#

Run the script lol?

#

It's scriptable bots from the people who own the server

opaque plover
hardy hedge
#

They can make JS files

#

That they can use to make their own bots so it uses scriptengine for it

surreal peak
#

bruh, this runs a discord bot from a js file?

hardy hedge
#

No it runs its own chat bot

#

In the mc chat

#

Similar to discord bot but nowhere near as powerful

#

So for example in the js file there would be something like this:

opaque plover
#

javascript out of all languages

hardy hedge
#

What's wrong with JS?

opaque plover
#

yeah no it's all good

hardy hedge
#

Not using LUA lol

#

Ah lol ok. Yeah JS can be funky

#

We use something like this at work so I thought it'd be interesting to implement it into MC in its own way

surreal peak
hardy hedge
#

There is nothing wrong with it if you're not an elitist which you are clearly showing in this chat. I get paid to use it at my job so clearly it has uses

surreal peak
#

it has its misuses

hardy hedge
#

I agree, it should not be used in a backend web framework, but it also has its uses

round fossil
#

I hate that every line in JavaScript can throw an error

#

i want my code to force me to handle errors by having errors as values etc

#

With JavaScript, that’s only partially possible without cumbersome design

surreal peak
#

glad you didnt ever throw a number in c++

#

you can throw anything you want there

dense leaf
#

me when typescript exists

hardy hedge
#

Beat me to it

surreal peak
#

:)

hardy hedge
#

It's not exactly a linter but in the basic sense I guess. TypeScript is very nice to code in

#

Way nicer than vanilla JS

surreal peak
#

just use c++

#

typescript is an excuse to not learn an unmanaged lang

dense leaf
#

or rust

round fossil
#

Exceptions in cpp should be used sparingly

#

They are dangerous

surreal peak
#

im scared of stack unwinding :(

hardy hedge
#

or a multi-platform app

surreal peak
#

i mean js, has its uses, web, thats literally it

round fossil
#

yea tho with a framework

#

Else u’re screwed

hardy hedge
#

You can use js without a framework

surreal peak
#

framework for what

#

a la jquery?

hardy hedge
#

No fuck that lmao

#

Vanilla JS is perfectly capable now

surreal peak
#

capable of what? modifying the dom?

#

or calling into libraries

hardy hedge
#

Clown reacts me lmao. Ok mr elite developer I'll step back into my cave of a novice and let the expert do his work

round fossil
#

normal js is probably never ever used in developing any website, I mean you choose a framework?

hardy hedge
#

You usually choose a framework yes but Vanilla JS is capable of almost everything JQuery does

surreal peak
#

now its "almost everything" already

#

its awful

hardy hedge
#

That's your opinion

surreal peak
#

sure

hardy hedge
#

I don't recommend using Vanilla js in websites but it can be done without JQuery

round fossil
#

be realistic tho, in the industry and for personal projects, barely barely anyone uses vanilla

hardy hedge
#

Well yeah for sure, I'm just saying JQuery isn't needed anymore if you opt to use vanilla

round fossil
#

and I’m talking about real web devs, not the people who are there to just learn dom with js for their first time

round fossil
#

Anyway fourteenbrush I don’t think cpp has the best language design around error handling, but thats my personal opinion

#

just like JavaScript

surreal peak
#

whats design has it thats different from other languages? apart from being able to throw anything you want and catch by reference

round fossil
#

I mean you referred to just exception throwing, error codes is imho much better, ofc if the eco system and the language is a proponent of it, else you land in an abstraction layer

surreal peak
#

yes

#

just yes

round fossil
#

Now yea, cpp is old so ofc its not fair to utterly flame cpp, or any other language for it

opaque plover
#

javascript was literally named javascript so that it would get more popular because of the word java

#

we can't not flame it

round fossil
#

kotlinscript

opaque plover
#

imagine

surreal peak
#

result types wouldve been a good thing if they were integrated in the lang, like rust

round fossil
#

I think the fact that JavaScript is dynamically typed makes the entire try catch and throw code control flow design so much worse

surreal peak
#

imagine a better world

hardy hedge
#

Lol now I am not saying JavaScript isn't deserving of it's slander, I agree with all these points

#

It's always horrendous to see a catch(e) in the middle of some giga function someone wrote in 2016

surreal peak
#

legacy code moment

round fossil
#

yea, I think TypeScript is generally a decent solution also, but it has some problems also :(

hardy hedge
#

Yeah very true. Using TypeScript after JS for a while is like a huge load off your chest, but it comes with its problems

hardy hedge
#

Oh man you can put python in java too

surreal peak
#

dont

hardy hedge
#

Lol I know I was just saying its strange

round fossil
#

what is it called, jython? Right?

hardy hedge
#

Yes

surreal peak
#

i thought you were talking about a scripting engine again

hardy hedge
#

I am

surreal peak
#

wait it is

#

we had a way for that, it was called invoking a script

hardy hedge
#

That's literally what a scripting engine is

#

It's built into Java

#

You just need to download the engines themselves

surreal peak
#

to me it seems like you gotta ask the question why you're uberhaupt trying to call python from java

#

just thoughts

round fossil
#

sounds ideal

hardy hedge
#

Sometimes people want to make it so they can modify their application for specific use cases by people or want people to be able to mod the code

round fossil
#

Most of py is in C anyway or so, so native language invocation speed boost? (/s)

surreal peak
#

i mean if you would call lua from c++ for plugins for games, ok thats just happens, but why python

#

not saying lua aint crap

hardy hedge
#

Well yeah that wouldn't be my first choice

surreal peak
#

can yo ugive me one usecase?

round fossil
#

replace skript

#

:,)

surreal peak
round fossil
surreal peak
#

so "python is good for ml" is nonsense

hardy hedge
surreal peak
#

like code generators?

hardy hedge
#

No, like making your application scriptable

round fossil
#

tbh data generators could be fine having it in py

surreal peak
#

mmh fair

round fossil
#

but i feel like the interoperability would suck, if anything

surreal peak
#

but imagine spigot had you write plugins in python instead of java

round fossil
#

myea, imagine that

opaque plover
#

i'd kms

surreal peak
#

i mean if you wanna make your application scriptable, why not do it in the lang thats its written in, ive seem that so many times

#

non technical users ig then

hardy hedge
#

It makes it easier for smaller things

#

It has its uses like I said

round fossil
#

idk if python is the ideal language for it

hardy hedge
#

No I agree with that

round fossil
#

but yea, having a separate language and system for things that can be “DSL-able” is sometimes a convenience

#

altho DSLs usually become a bit cumbersome and annoying to maintain in practice xD

surreal peak
#

you might think about it that way

night knoll
hardy hedge
woeful pasture
#

its great for ML mockups etc which is exactly what its used for. Just because the libraries are in C doesn't devalue its ML capabilities as a language

surreal peak
#

i meant to say "cuz python is fast for ml"

#

i mean you, woulve been a bit harder to call c

woeful pasture
#

no real human thinks that

#

unless you're on twitter

#

than I wouldn't doubt it

alpine anvil
lunar nacelle
#

how do I find these method name in 1.20.4 nms

clever crag
rancid fern
#

Do yourself a favour and use mojang mappings

tidal basin
#

very basic code, but if it can be upgraded... 👍

jagged rock
#

Huge room for improvement

tidal basin
jagged rock
#

We can start by arguing over consistency, caching config values

#

Single name variables

#

Naming conventions, all of that

#

Duplicate collection calls

tidal basin
jagged rock
#

Single letter*

tidal basin
#

hmm

jagged rock
#

static abuse just for the sake of it

tidal basin
jagged rock
#

There's a lot

tidal basin
#

no performance leak?

jagged rock
#

One or two but they're minor

tidal basin
jagged rock
#

Figure it out :)

tidal basin
#

...

sly jackal
#

yeah I was just bothered by the all caps manager variable names xD

tidal basin
jagged rock
#

Opposite

tidal basin
sly jackal
#

it doesnt need to be static

tidal basin
#

okay

sly jackal
#

but imo it doesnt really matter

#

like you are probably accessing it in a lot of places

#

on my plugin I have created a class that just loads the config.yml file so I dont have to search in the yml file manually everywhere its used

#

but thats more of a convenience thing

tidal basin
jagged rock
#

?di

rich fogBOT
jagged rock
tidal basin
surreal peak
#

dont expose collections

tidal basin
surreal peak
#

inject some wrapper or somethinh

tidal basin
#

huh

surreal peak
#

like di

tidal basin
surreal peak
#

wrapper thing for your collection, maybe some extra logic associateted witj it

#

class

#

wrapper class

#

some manager thingi

#

we are not making a spaghetti, we are making a lasagna

tidal basin
sly jackal
#

whats the difference

surreal peak
#

between spaghetti and lasagna?

sly jackal
#

look when you are accessingthia collection from the outside and then see if maybe all you have to do is just add a few mthods in your static class

surreal peak
#

if you want to associate logic with modifying that collection

#

directly modifying it wont run said logic

sly jackal
#

yes I know

surreal peak
#

also outsiders shouldnt be allowed to change things direcctly

#

a la unrelated systems

sly jackal
#

but I think depending on where youare using this a wrapper might not be needed

surreal peak
#

conclure writing the bible

round fossil
#

prefer Map::getOrDefault to Map::get null check if you're doing something with the value.

Some of your methods are really gigantic, like the one in RepairManager::initAutoRepair which also declares a fat callback, cut it down if you can.

Good that you use ur plugin logger and keep bootstrap logic to ur bootstrap/entry point function.

As pointed out by the others, but the static task scheduler can be questionable, esp since chances are big as you scale code you want to have different thread pools and ways of dealing with multithreading depending on module, sharing the same TaskScheduler could be problematic from a testability, maintainability and modular perspective. Let alone I saw some random static "singletons" floating around in different classes, reconsider that design choice.

Someone else may have pointed it out, but you rarely ever keep all the interfaces in a singular package named "interfaces", its a less ideal structure.

Your config manager sucks.

Me personally likes when instance methods and instance fields are called with this and super keyword though I have come to understand its more preference so this is soft.

Your command class can derive TabExecutor instead, it also has a goofy name, the acronym BTM may not be entirely given.

round fossil
#

well I havent read every single line, but I thought I'd give you some advice on different levels :]

tidal basin
round fossil
#

CooldownManager iirc

tidal basin
#

oh yeah

tidal basin
# round fossil CooldownManager iirc

but, I can't use getOrDefault here?java public Duration getRemainingCooldown(UUID key) { Instant cooldown = map.get(key); Instant now = Instant.now(); if (cooldown != null && now.isBefore(cooldown)) { return Duration.between(now, cooldown); } else { return Duration.ZERO; } }

sly jackal
#

I usually just use this in constructors or naming conflicts xD

round fossil
#

this is esp good when u work w ppl who may read ur code on lets say GitHub or on a paste/gist

sly jackal
#

well what do you want to happen when there is no cooldown for the key

#

yeah true

#

I never look at it from that perspective because usually its just me in my nice ide with rainbow colors

tidal basin
#

but Duration isn't Instant

round fossil
#

I mean you have Instant.MAX and Instant.MIN/EPOCH

#

likely one of those that u wna use

tidal basin
#

hm

sly jackal
#

or use Instant.now

#

should also work

#

is now before now?

tidal basin
sly jackal
#

right

tidal basin
sly jackal
#

so then it will also use duration.zero

round fossil
#

but yea PauLem, fyi, I said prefer, ofc there are moments when a null check is more suitable, for instance in multithreading when you design thread safe classes you may opt for explicit null checks at times (tho more in general)

sly jackal
#

but ultimately it will be zero if you calculate the duration between probably

tidal basin
round fossil
#

yes, that was just an example

round fossil
#

you have to decide for urself which one is better

sly jackal
#

I guess all you have to check is make sure there is no negative duration?

#

but idk how you handle removing stuff from the map anyways

#

i havent seen this file xD

tidal basin
#

well

#
public Duration getRemainingCooldown(UUID key) {
    Instant cooldown = map.getOrDefault(key, Instant.now());
    Instant now = Instant.now();
    if (now.isBefore(cooldown)) {
        return Duration.between(now, cooldown);
    } else {
        return Duration.ZERO;
    }
}```
#

let's compact this

round fossil
#

maybe u wna do it like

#

getOrDefault(key,now)

tidal basin
#
public Duration getRemainingCooldown(UUID key) {
    Instant now = Instant.now();
    Instant cooldown = map.getOrDefault(key, now);

    return now.isBefore(cooldown) ? Duration.between(now, cooldown) : Duration.ZERO;
}```
tidal basin
round fossil
#

so that they use the same yk yk

round fossil
#

yea I suppose

#

my brain is a bit fried atm so maybe we got it logically invalid, but yea

tidal basin
#

can optimize this toojava public boolean hasCooldown(UUID key) { Instant cooldown = map.get(key); return cooldown != null && Instant.now().isBefore(cooldown); }

sly jackal
#

optimize is relative

surreal peak
sly jackal
#

you are arguably making it less readable to a point

tidal basin
#
// Check if cooldown has expired
public boolean hasCooldown(UUID key) {
    Instant now = Instant.now();
    Instant cooldown = map.getOrDefault(key, now);
    return now.isBefore(cooldown);
}```
sly jackal
#

there is something thats easy to read about just the if else imo

sly jackal
#

idk the documentation for negative durations

#

like maybe thats not something you want

#

or maybe it doesnt matter

tidal basin
#

to check if there is a cooldown

sly jackal
#

oh

round fossil
tidal basin
#

oh, I re-found that```java
// I like spaghetti. (I'll improve this)
if(cooldownManager.getDefaultCooldown() == 0) {

useRepair(player, item);

} else if(cooldownManager.hasCooldown(playerId)) {

alertCooldown(playerId, player);

} else if(cooldownUses.containsKey(playerId)) {

isInMap(playerId, player, item);

} else {

// Put the player in map
cooldownUses.put(playerId, 1);

// Make repair
useRepair(player, item);

}```

#

lol

surreal peak
#

another brain hurt by the brainrot

#

wouldnt even know how that sentence makes sence tbh

tidal basin
#

x)

sly jackal
#

wtf is isInMap

#

im too lazy to open the file on phone

round fossil
clever crag
clever crag
#

I think you need add this feature

tidal basin
#

yeah

clever crag
#

Maybe this code will help you

    for (String key : config.getKeys(true)) {
            if (embeddedConfig.get(key) == null) {
                config.set(key, null);
            }
        }
remote kiln
surreal peak
#

cant you cast GSON.fromJson to T instead of the cf?

remote kiln
#

oh you're right ty

jagged rock
#

You could use a MongoCollection<T> internally and avoid just gsoning stuff

#

have an abstract codec or something

#

do it the proper way

tall trout
#

Hi can anyone help me with my plugin I am coding this is my first kinda big plugin so pls don't judge and don't say How i could tidy it up or put some thing in different classes. So anyway I feel like my test server is getting bad performance with this plugin enabled can anyone see anything obvious that is causing performance issues I think it might have something to do wtih the task scheduling but idk. Thanks

WardenRelics(Mail File): https://paste.md-5.net/rovuxokegi.java
RelicManager: https://paste.md-5.net/qogipeheli.java
Relic Of Travel(An example of one of the relics): https://paste.md-5.net/erayepefac.cs

surreal peak
#

dont register a new listener in RelicOfTravel constructor every time

#

imagine you ending up with thousands of those items

#

id say have a global listener, which keeps track of those items through a RelicManager and propagates the event to the correct items

#

also youre never doing any cleanup when the player leaves the server

#

like i assume your listener needs to get unregistered, its broken though

#

just so much code that i can barely see whats happening

#

you sure you cant do certain things event based rather than having a bunch of tasks checking for things every tick?

surreal peak
noble eagle
#

outrageous

surreal peak
#

i believe ive seen that code before

novel meteor
# tall trout Hi can anyone help me with my plugin I am coding this is my first kinda big plug...

Calling item.getItemMeta() will tank performance if you do it too much
Every call creates a copy of the item data.
Create a temporary variable ItemMeta and call the getItemMeta just once, then do the checks.
This is not this method specific, you do it in several places.

Also, I would recommend using PDC to identify the items, not item name.
Ppl can change that (unless you specifically forbid the usages of anvils or something)

surreal peak
#

i mean just clean up that mess before you start thinking about anything else

sleek shard
surreal peak
#

proxy is with an y

sleek shard
#

yea i know

surreal peak
#

oh well the thing is called proxi, cringe

dense leaf
surreal peak
#

id maybe use a MethodHandle instead of a Constructor

#

in your entity factory

sleek shard
#

yep

surreal peak
#

and do some proper exception handling

#

is a DefaultEntityFactoryMaker like a DefaultEntityFactoryFactory? 🤓

dense leaf
#

oh my god

#

is that actually a thing

surreal peak
#

and i prefer doing direct initialization

round fossil
#

ConcurrentMap /:o

round fossil
#

Ur proxy singleton variable should be named lowercase like normal variables as its not a constant

#

You could probably allow class visitor to have separate methods for different types nodes rather than using the same callback for all types of nodes

#

first created data could be an Instant instead ofc u trade a bit of memory then but thats that

#

Instead of nested factories u may wanna look at abstract factory pattern

junior holly
#

Why not one listener and just 2 methods for handling the stuff you want to do

#

That's fine? I mean the point is that it's a listener for the player join event so

#

Why make multiple listeners

#

Separate the concern by methods mane

#

If you want multiple listeners then go for it, but if they're not backed by heavy functions then I don't see a lot of benefit in multiple listeners

wintry fern
#

NuclearKat is correct here in that only one listener needs to be used

#

not sure why relation matters here, and you only need one method technically

#

this is why conditionals are a thing in code

#

setup an appropriate condition to be checked and you can decide what code needs to be ran lol

jagged rock
#

Yes

#

Has to deal with separation of concerns

#

If you have two very distinct systems, there's no reason why they should share the same listener

pine grail
jagged rock
#

Quite situational

pine grail
woeful pasture
jagged rock
#

Doesn't scale well when your codebase is like 30k+ lines long

sly jackal
#

using multiple listeners is fine

jagged rock
#

Depends

#

I've been making managers register their own listeners for removing residual data

#

It's not 100% ideal but it's self-sustained

#

It allows me to copy over the project and not have to worry about registering listeners

sleek shard
#

Honestly having multiple listeners will allow you to debug if there's lag or not with spark, as you can see which class it's coming from, rather than having to search a method for a specific line, specific method, etc.

surreal peak
#

init method 🤔

dense leaf
#

<init> go brr

surreal peak
#

Meow.<init>

night knoll
#

innit

surreal peak
#

what

dense leaf
round fossil
#

ehrm, what the sigma, why are you using kotlin? 🤓☝️ (/s)

#

well I like to use version catalogues, altho Ig that’s more of a preference

dense leaf
#

oh yea

round fossil
#

Your command object has one large register method that both registers and implements all of ur commands, not sure how much of an issue that is in kotlin infrastructurally speaking, but I mean you could probably extract that out for instance (i think I saw some other place where there is a bunch of nested higher ordered functions and first class functions)

dense leaf
#

gradle moment

round fossil
#

yea fr

dense leaf
#

commands aren't the prettiest to do

round fossil
#

that’s true

#

its just gonna be input parsing one or another way at the end of the day

dense leaf
#

yeah

#

it looks weird

round fossil
#

I think it looks good otherwise :)

#

Oh wtf yea that looks so goofy

dense leaf
#

yea

#

i'm planning to add custom data tags

#

to schematics

#

like, adding in some other options to the nbt file

dense leaf
#

i do like the format tho

round fossil
#

ah yes

dense leaf
round fossil
#

I just said that because it reminded me of working with schematic files, well that was long time ago but yup (i was a static abuser back then)

surreal peak
#

would write this a bit more formatted lol

sly jackal
#

insert hadouken here

surreal peak
#

ha what

sly jackal
novel meteor
#

damn, sniped

surreal peak
#

here you have the gif

sly jackal
#

oh i didnt know there was a gif

dense leaf
tall plover
#

Hey, could you review this code?

#

1s

#

thanks

round fossil
#

handleMenu is huge

#

maybe extract out smaller methods

dense leaf
#

?gui

dense leaf
#

don't do a switch on the slot

round fossil
#

@surreal peak whats ur opinion on using result objects in java?

#

Like not Optional cuz it sucks, but something similar

tall plover
round fossil
#

Well I mean in Java particularly

#

as opposed to using throwables

woeful pasture
round fossil
woeful pasture
round fossil
#

Ah okay

woeful pasture
#

I use both java and kotlin

round fossil
#

yea, well do u always substitute pattern matching on a result to using throwable control flows?

woeful pasture
round fossil
#

myea, well I was considering doing the same

woeful pasture
#

Take a look I still throw errors rn but it's because I haven't introduced a proper logging and killing mechanism yet

round fossil
#

I thought I’d just use exceptions as a means to represent stacktraceable errors, that is I convert the result into an exception and then send it to the slf4j api

#

but design wise relying on result objects entirely

#

well this is all very hypothetical, not sure how great it will scale w my app api and everything, but i really liked the idea of it at least

woeful pasture
#

If you wanna take a look at how it generally applies my project above uses them pretty much exclusively I have a few things to switch over but it's almost entirely results

surreal peak
round fossil
#

Subtypable optionals I suppose

surreal peak
#

also what does better mean

round fossil
#

sealed interface Option permits None, Some

woeful pasture
#

I find errors as values generally nice

round fossil
#

for example

surreal peak
#

would only introduce dynamic dispatch overhead

surreal peak
#

and if Option.NONE is a static constant of class Option.None, that could cause a classloader deadlock

round fossil
woeful pasture
round fossil
#

but just look at kotlin for instance, they have it built in (ofc its not nearly as powerful and semantic)

surreal peak
#

as powerful as what?

#

im not following

woeful pasture
#

Something like rust or go I presume

round fossil
#

Kotlin has its nullability safety semantic

surreal peak
#

which get massacred by the jvm

round fossil
#

if a type A equipped with a function B that returns C?
a subtype AA of A can return just C on that function B

round fossil
round fossil
woeful pasture
#

Javas optional implementation is subpar too

round fossil
#

Yes

surreal peak
#

subpar?

round fossil
#

basically not enough

round fossil
woeful pasture
round fossil
surreal peak
#

what did that even mean? ofc AA can return C, is it supposed to return a subtype of C?

round fossil
#

class A {
func B -> C?
}

class AA : A{
func B -> C
}

where C? means nullable of type C

surreal peak
#

ah

round fossil
#

with Java there is no such semantic unless u invent it w some sort of polymorphic structure

#

like my goofy example w a sealed interface, or well with sealed abstract class

#

Anyway I was just curious what ur thoughts on using result objects over normal throwables in java are fourteenbrush

surreal peak
#

i dont like stack unwinding

#

i once saw smile returning throwables instead of throwing them

woeful pasture
#

Based

#

Incredibly based

surreal peak
#

what kind of reaction is that

round fossil
#

ofc

surreal peak
#

glad c doesnt have exceptions

#

not saying c is good, its still a pile of old crap thats still in use for whatever reason

round fossil
#

something like this

Result(T success, F failure){
func raiseException() { /*throws something */ }
}

and then an Option class of some sort

surreal peak
#

but what was in the first place the point of throwing exceptions instead of simply returning an error object

#

these days kids just throw them exceptions, dont document it and expect us to do smth about it

round fossil
#

i feel like with checked exceptions it can make sense since u’re forced to deal with it

surreal peak
#

as in returning error objects gives (in my eyes) a better guanantee that the end user actually handles those fault cases

round fossil
#

but unchecked exceptions, oh jesus

surreal peak
#

in kotlin there isnt even a concept of checked exceptions iirc

woeful pasture
#

Only unchecked

round fossil
#

Yea because its annoying since we started to use exceptions for checking dumb invariants that may not even be true due to the programmer themselves messing things up

surreal peak
#

unwinding the stack to let the caller handle that either way, sounds familiar to a method return

round fossil
#

and then having a checked exception for something that is rarely ever gonna be thrown but only if the programmer is dumb enough to forget about the invariants and state of the system

surreal peak
#

rust does a good job with Result<T, E>

woeful pasture
#

IOException my beloved ♥️

surreal peak
#

UncheckedIoException 😳

round fossil
round fossil
#

soo what’s ur actual opinion on it fourteen

surreal peak
#

it scares me how many times i see just a e.printStackTrace() on plugins code

#

opinion on Result?

round fossil
round fossil
surreal peak
#

i mean there are no language design semantics around it

round fossil
#

primary goal being to avoid the hassles of unchecked exceptions

surreal peak
#

having something like rust ? or odins or_return wouldve been great

round fossil
#

definitely

surreal peak
#

but at some point we gotta realize that java isnt out destination

round fossil
#

if let uwu

#

i mean java has the valhalla non nullable type jep that hopefully is released one day

surreal peak
#

building on a mountain of bad decisions doesnt mean the language is getting any better

#

but thats just my opinion

round fossil
#

yea well its mostly to do with optimizing generics and enhancing its semantics and ergonomics

#

But well, fuck okay, without side tracking

#

Handcrafted java result class, valid or nah?

surreal peak
#

thats too abstract for me, i gotta know how well its usable

round fossil
#

How do you evaluate usability?

surreal peak
#

you can go whateevr direction you want with that, what are you gonna do? write a gloried Optional and realize you just reinvented the wheel?

round fossil
#

I mean yes but then again Optional doesn’t have subtypes to express absence/presence of a value

surreal peak
#

why would it need subtyping?

round fossil
#

A::B returns Maybe<C>

AA::B returns Yes<C>

#

so in the case of having terms expressable in AA, we don’t need to evaluate Maybe::isPresent

surreal peak
#

how are you gonna know if you only know A exists (read as liskov)?

#

if A is abstract

round fossil
#

I mean maybe you have an instance of AA?

#

and I mean it could be as simple as a type hierarchy of animals
Animal::getPrey -> Maybe<ResizableList<Animal>>
Bear::getPrey -> Yes<ResizableList<Animal>>

surreal peak
#

sounds like pattern matching

round fossil
#

Well I mean what if we happen to just have a term of Bear, the at compile time we already know it will yield a list of preys

surreal peak
#

ye

round fossil
#

instead of having to evaluate Maybe::isPresent => Maybe::unwrap

#

since ::unwrap may panic if ::isPresent yields false

#

Well Idk maybe its just me overthinking and all I need to do is to shove in those Optionals

#

@woeful pasture but u support it riiight?

surreal peak
#

ig compilers arent smart enough

round fossil
surreal peak
#

uhh

#

never finished it

#

i got so much stuff to do

round fossil
#

i guess u’re compiling math expressions lol

#

yea fair

surreal peak
#

💀

#

i was working on some kind of assembly lang with a runtime but i abandoned it

#

started rewriting it in c++ and that didnt end very well

round fossil
#

Sounds a bit masochistic, but at least u tried

surreal peak
#

also writing a partial c parser atm

round fossil
#

partial as in?

surreal peak
#

to parse simple structs and function ptrs after preprocessing

#

to generate bindings

round fossil
#

Ah okay

#

in cpp aswell?

surreal peak
#

odin

#

better than c++

#

i also let my eye fall on nim

round fossil
#

ah, C alternative

#

fair

surreal peak
#

looks a bit too script alike though

#

might just write my own lang

woeful pasture
surreal peak
#

unsafe { unwrap_unchecked() }

round fossil
#

if only

dense leaf
surreal peak
surreal peak
#

best argument against operator overloading:

That just makes code unreadable. You think it's a comparison, but someone on your team redefined it as a command to the coffee machine to give you tea next time.

round fossil
round fossil
surreal peak
#

definitely does not start a bitcoin miner

wintry fern
dense leaf
#

the example (example module) logs this:

#

i haven't actually tested out the other asset resolution strategies, should probably do that

#

i should probably add the namespaced key regex

round fossil
#

Did you code this with regard to java interoperability by chance or nah?

dense leaf
round fossil
#

I was mainly curious, I mean apis and libs when written in kotlin do try to consider the java side of things

#

take moshi for example

dense leaf
round fossil
#

myea well one of the appeals with kotlin is that u can write it easily to fit both java and kotlin devs extending the overall appeal ^^

opaque plover
surreal peak
dense leaf
surreal peak
#

internal becomes public

dense leaf
#

oh

opaque plover
dense leaf
opaque plover
#

they don't even mention it in that page 😦

#

they just silently kill it

dense leaf
#

yeah

opaque plover
#

like surely they can sanitize the name

#

but they dont

dense leaf
#

"you should only use it for tests" 🤓

opaque plover
#

lol

#

where does it say that

dense leaf
opaque plover
#

do you know about kotlin notebook

#

looks like a cool thing

#

idk how id find a usecase for it though

dense leaf
#

is that like pynb

opaque plover
#

maybe docs

#

Kotlin Notebook is an interactive tool that lets you mix code, visuals, and markdown in one document. You can use notebooks to write and execute code in sections known as code cells, see the results instantly, and write down your thoughts. This setup makes it an excellent tool for rapid prototyping, analytics, and data science.

#

idk pynb

dense leaf
#

like jupyter

opaque plover
#

idk jupyter

#

looks cool for data visualization

dense leaf
#

except that jupyter is py

opaque plover
#

idfk what jupyter is

#

well i know now

#

that it's pretty much kotlin notebook

#

but yeah i don't like py

dense leaf
#

good

opaque plover
#

please call me a good boy

#

please

dense leaf
#

good boy~

opaque plover
#

thankssssssssss

#

:3

dense leaf
#

!!

dense leaf
#

not at home

opaque plover
#

how do i gif a gif

dense leaf
#

oh

#

that doesn't show on mobile

opaque plover
#

common discord mobile l

dense leaf
#

real

surreal peak
opaque plover
#

yes but we want to use some long name

surreal peak
#

just dont?

dense leaf
dense leaf
#

you wouldn't get it

opaque plover
#

MAKE FUNCTION NAMES THAT JUST WOULD NOT EXIST IN JAVA

#

SO THEY GO POOF

#

PLUGIN CREATORS WILL BE FORCED TO USE KOTLIN

#

DAFEIST IS SPONTANEOUSLY COMBUSTING!!!!!!!!!!

#

THE GOAL OF COMBUSTMC IS ACHIEVED

dense leaf
#

kwall

surreal peak
#

🤔

dense leaf
#

RANDOMLY

#

every time you make a new class you flip a coin whether it should be kotlin or java

junior holly
#

Fuck it, why not just pseudo code

opaque plover
#

bc we gonna compile it

junior holly
#

Nah just leave that to other devs

#

They can figure it out

opaque plover
#

ok fair

dense leaf
#

fair

junior holly
#

No documentation either

dense leaf
#

no no

#

we do docs

#

juts

#

a bit differently

sleek shard
#

Been working on the database side of things - got the main start of it done, no functionality to it yet.
Just want opinions on the database and mongo project to see if it's laid out well or not. It's based upon Morphia, just making it custom for versioning support and such
https://github.com/ignPurple/proxi

GitHub

An ORM Entity system made for Java. Contribute to ignPurple/proxi development by creating an account on GitHub.

dense leaf
surreal peak
#

dunno how much that gets called but its a factory

round fossil
#

yea probably a good idea if ur orm lib depends on class scanning and invoking those class members at runtime

surreal peak
#

also not a big fan of printing a stacktrace and simply returning null

round fossil
#

Which class is that method in @surreal peak ?

surreal peak
#

uhh

#

Ctrl + k btw

round fossil
#

Im on phone :(

surreal peak
#

dunno then

round fossil
#

but yea the error handling can definitely be better

surreal peak
#

no funnier things to do on phone?

round fossil
#

I think you got me good there 😒

surreal peak
#

lol

sleek shard
surreal peak
#

yes

sleek shard
#

aight cool

#

Aight I commit and pushed for that change, and instead of just printing the stacktrace and returning null, I'm just throwing the custom exception instead

sleek shard
#

oh god damn it, don't you love it when you don't click the big push button

surreal peak
#

you have a button to push?

#

im a cli user

sleek shard
#

fair, I just use the intellij way

round fossil
#

@sleek shard you may want to let the api consumer pass their own lookup instance

#

If they want to use it on non public stuff where strong encapsulation such as module encapsulation stops outer modules from messing with those

#

well just an idea

#

^^

sleek shard
#

Whatchu mean by that exactly? remove the static on it?

#

Or?

round fossil
#

What I mean is that the api user of ur library maybe have private constructors, which means u wouldn’t be able to access it

#

U’d get an illegal access error/exception

surreal peak
#

doest lookup() have full access?

round fossil
#

in such a case, it may be beneficial to let the api user pass a lookup instance that is allowed to

#

only public stuff

round fossil
#

i think?

surreal peak
#

but theres also publicLookup()

round fossil
#

Thats java 8

#

jpms strong encapsulation was introduced j9

surreal peak
#

uh idk my browser always gives me that

round fossil
#

Right?

#

Lol its cuz so many things still run java 8 i think or yea

surreal peak
#

public static MethodHandles.Lookup lookup()
Returns a lookup object with full capabilities to emulate all supported bytecode behaviors of the caller. These capabilities include full privilege access to the caller. Factory methods on the lookup object can create direct method handles for any member that the caller has access to via bytecodes, including protected and private fields and methods. This lookup object is created by the original lookup class and has the ORIGINAL bit set. This lookup object is a capability which may be delegated to trusted agents. Do not store it in place where untrusted code can access it.

sleek shard
#

I'll test with a private constructor rq

round fossil
#

Yea try it out

surreal peak
#

show code

round fossil
surreal peak
#

havent used that stuff much

#

ig you need privateLookupIn then

sleek shard
#

I tried that too

#

still same thing

#

I'll see if there's a workaround

surreal peak
#

reflection

round fossil
#

the so called lookup class

#

Well skinny I know of what an ORM is, I know the design patterns and things but ofc there’s stuff that I have to read to understand, when reviewing code its a process of trying to first understand what the thing does, then see if you think it can be improved, that can be in terms of optimization in terms of time and space footprint, readability, maybe just better infrastructure, or maybe the names of classes methods etc are lacking etc

#

But yea @sleek shard letting us pass our own method handle may not be a dumb idea

sleek shard
#

Yea

round fossil
#

anyway iirc privateLookup works as long as its in the class itself

#

That is u need to call privateLookup inside the class itself somewhere

sleek shard
#

Ohhh I see

#

okay

round fossil
#

well, there are edge cases w modules, but eh basically what i said above

sleek shard
#

One thing I can do - since I use bytebuddy, I could add a default constructor automatically

#

I think so anyway

round fossil
#

Yea, i mean there is unsafe

#

But that’s unsafe

surreal peak
#

Unsafe::allocateInstance 🐸

round fossil
#

And yea even reflection struggle with the same access privileges as method handles due to strong encapsulation

sleek shard
#

it would work Thonk

#

@round fossil do you advise against using Unsafe#allocateInstance

#

because it WOULD work that way

#

no constructor needed at all

surreal peak
#

it doesnt initialize any fields

#

dont use it

sleek shard
#

Ah okay

woeful pasture
#

well idk if its currently deprecated but its being replaced so

surreal peak
#

they gotta give us alternatives then

sleek shard
surreal peak
#

its not initialized in a constructor

sleek shard
#

Yea that's the point of the default constructor, just to create an instance of the class

#

That's what I wanted the whole time

surreal peak
#

print the uuid instead

sleek shard
#

Oh if it's not final then it's null

#

interesting

surreal peak
#

if its final it should also be null

sleek shard
round fossil
#

https://gist.github.com/conclube/ec44a58feff052a37142ba230cddc2fa

Feel free to pick on anything ^^, some notes just:

  • I wrote a monadic Either union type to deal with pipelining the composition of functions
  • I am mostly concerned about ExtensionLoader::collectExtension (its so clumsy just),
    as well as the candidates temp map since ExtensionHolder just encapsulates ModuleReference and Extension right now (like perhaps its unnecessary?). In the way its coded a lot of these functions are barely unit testable.
round fossil
#

lmao

alpine anvil
jagged rock
#

Spacing is inconsistent

round fossil
round fossil
jagged rock
#

Usage of Eithers, left/right -> Dedicated calss

jagged rock
round fossil
#

ah yea

round fossil
alpine anvil
# round fossil i mean i know about the theory

okay so lets say i have a db, in this db i have tickets but each ticket can have different data, atm i just have common data as collumns and individual data as a json value can i design that better

jagged rock
#

Personal peeve of mine but I'm starting to dislike seeing new after ()'s

#

Solution for this is either a dedicated method, or the usage of static factory pattern

#

Ideally both

#

Especially because if the structure changes to a map or something there are a lot of calls you gotta rewrite

jagged rock
#

Eh

#

It was an issue in java

alpine anvil
#

no new if new doesnt exist

jagged rock
#

Started getting picky about it after writing my command system

round fossil
#

yeah its ugly to have a direct instantiation but that class is encapsulated within the bounds of the package so it shouldn't be an issue, if I change the underlying data structure I'd have to refactor those lines regardless

jagged rock
#

does this need to be a set? What's wrong with a generic collection

round fossil
#

ModuleFinder::findAll produces that type

jagged rock
#

Collection will still work

round fossil
#

yes but I don't want to iterate through dupes

alpine anvil
round fossil
#

so u're blobbing it rn?

#

@jagged rock btw illusion, what's ur thoughts on this:

" I am mostly concerned about ExtensionLoader::collectExtension (its so clumsy just),

as well as the candidates temp map since ExtensionHolder just encapsulates ModuleReference and Extension right now (like perhaps its unnecessary?). In the way its coded a lot of these functions are barely unit testable."

#

because that's what I'm mostly fixated at

alpine anvil
round fossil
#

how structured is this json?

#

like do u have set formats or do the formats vary too much?

#

for example can you structify the different formats of ur json?

alpine anvil
#

i dont think so, each ticket type would have different data like i have a commission ticket which would have like budget, name, description etc etc or i could have a suport ticket would would have other data relating to that

jagged rock
#

Hm

#

failedExtensions.add -> fail(descriptor, reason)

round fossil
#

do u think candidatescould be completely eliminated?

#

i mean if u got another design in ur head

jagged rock
#

I barely understand what half of this does anyways

round fossil
jagged rock
#

But I'd like to see more Result objects and less throwing data in a map somewhere to get it later

jagged rock
#

That way you can create controlled Result objects to unit-test specific methods

alpine anvil
#

but one @late smelt and @woeful pasture said to just have 1 table

round fossil
jagged rock
#

the Eithers become results too

round fossil
#

yea epic there's ofc advantages and disadvantages

jagged rock
#

Maybe cache the empty ModuleFinder

woeful pasture
#

in your case the advantages far outweigh the disadvantages

round fossil
#

idk exactly what data u're storing epic

round fossil
jagged rock
#

Any guarantee this won't be empty?

alpine anvil
round fossil
woeful pasture
#

you would need thousands and thousands of simultaneous tickets to even maybe strain this system.

round fossil
#

epic tbh it sounds like u maybe dont even need to have it that relational here

#

so one table might be the solution

#

i mean think about it, will u ever need to exclusively fetch specific fields from that json structure?

#

or ru just gonna blob fetch it?

alpine anvil
#

True theres no data in it that id need to fetch from so json blob would work

sleek shard
#

would appreciate stars if anyone like's the project

placid gulch
#

How is this different from using MongoDBs driver POJO?

sleek shard
# placid gulch How is this different from using MongoDBs driver POJO?

Basically - with this, it's going to include versioning of fields and an integrated DAO system, it will also have redis support inside of it and you can use redis and mongo in the same dao to retrieve entities from the specified databases. It will try and receive the entity from redis first, and if it doesn't exist - then it will do it from the mongo.

The way that the versioning of entities will work inside of the dao is -
The IDEntityDAO #createDefaultEntity will have all the default fields defined when it's called. Allowing it to modify the retrieved entity from the database, and adding new fields which exist with their default values

Example-

public class TestDAO extends MultiDatastoreDAO<UUID, TestEntity> {
    
    public TestDAO(Datastore redisDatastore, Datastore mongoDatastore) {
        super(TestEntity.class);

        this.addDatastore(redisDatastore)
            .addDatastore(mongoDatastore);
    }

    @Override
    public TestEntity createDefaultEntity() {
        return new TestEntity(UUID.randomUUID(), "New String Field" /* Added after the entity is stored inside of the database */);
    }
}

// Old Entity which is stored in the datastore

{
    "_id": {"objectid"}
}

// Entity when it's retrieved from the database and versioned using the createDefaultEntity

{
    "_id": {"objectid"},
    "test": "New String Field"
}
#

It will also have a custom metadata field inside of the database, which stores what fields are currently in the entity.

placid gulch
#

Idk, I just don't see the usecase over just using Mongodb + Redis + POJO. I don't see what can't be achieved with just using those opposed to this?

sleek shard
#

One problem I noticed is - when retrieving an entity from the database, instead of having some fields which you NEWLY added inside of the entities as the value you want them - they will just be null because the data doesn't exist inside of the database.

#

If you understand what I mean by that

#

Unless you use some custom codec for the classes you grab from the databases, which is just a bigger pain instead of it being done automatically for you.

placid gulch
#

I mean you can just do migrations. Which is the industry standard way when adding/removing fields in a db.

sleek shard
#

Yea, and this is basically what this would do for you automatically - in a way

placid gulch
sleek shard
#

Personally I never heard of mongock

surreal peak
#

shouldve called it caveman

sleek shard
#

I mean I honestly made this project for some fun - just to have a better portfolio of working with db's and stuff like bytebuddy

dense leaf
#

does vanilla have codecs for entities?

#

surely for the world entity saving

#

so i don't get why you couldn't use that :p

#

dfu ❤️

willow bone
round fossil
#

Is there an absolute need to use Java 22?

#

I mean Java21 is LTS so its often nice when libraries support that yk

#

Other than that maybe you wanna make space for us to pick different random algorithms (instead of strictly and internally using Random)

Try to pick an initial capacity that’s relevant to ur collections when possible, not only when constructing one collection from another .

I personally don’t like when libraries expose the usage of lombok, since it can force the library user to support it if they depend on the source jar at compile time for example

surreal peak
#

also remove .idea

#

and exposing collections is like nah

#

there seem to be a lot of redundant lookups

#

and what on earth is this

#

O(n^3) how fun

#

what a monstrosity on its own

sly jackal
#

how would you do it then

surreal peak
#

well first of all use a norma loop, that makes that atomic int go away

#

also doing that isEmpty check is useless

sleek shard
#

hi nerds :D

surreal peak
#

nerd

round fossil
willow bone
willow bone
round fossil
#

The real problem with using AtomicInteger and just using getAndIncement, set, get, incrementAndGet etc is that they follow semantics of memory ordering effects of volatile, which means that it also flushes local caches since the value of the variable should be as up to date as possible, which is useful in multithreading where memory visibility can become an issue, that is two threads observe different values for the same variable

Edit which is why getPlain and setPlain is recommended as they behave as normal variable reads and variable writes

surreal peak
#

nerd

cobalt trellis
#

uses lazySet with no knowledge of anything whatsoever

round fossil
#

lazySet or weakSet?

surreal peak
#

how can a set be lazy?

cobalt trellis
#

I mean weak is for CAS

surreal peak
#

ah

round fossil
#

I guess memory fences are a better way of lifting the constraints of memory ordering effects

#

But yea you could technically use lazySet to CAS also if you do it correctly

surreal peak
#

ig im not fully awake yet hold on lol

round fossil
#

weeell idk if there’s so much to wake up to

#

I mean its just that volatile is nice, but its TOO ExpEnSIvvE, so java obviously has ways to decrease the constraints of memory ordering effects yk

#

So iirc there’s acquire, release and opaque (one behaves like atomic but for writes only, one behaves like atomic but for reads only, and idr the property of the third one)

#

and then there’s memory fences, which… well they do the same thing (decrease contraints, but its useful if you have multiple state variables that have invariants to each another)

surreal peak
#

whats the opaque?

#

ah thats really a thing

round fossil
#

yea

surreal peak
#

sounds like its time to watch another one of those two hour videos about javas memory model

round fossil
#

Lmao

#

But then i think acquire and release were just the volatile ones with less contraints, right?

surreal peak
#

idk i only know those are for loads and stores

round fossil
#

anyway the only mystery is weakSet which is like, it may fail for no reason on certain machines, so its unreliable unless you’re invoking until it eventually succeeds

surreal peak
#

:/

round fossil
surreal peak
#

maybe i should read it

#

the only book around concurrency i read is "operating systems in java" or smth

rancid fern
#

👀 java concurrency book?

surreal peak
#

didnt knew it either

round fossil
#

Java concurrency in practice

#

Its written by a some of the java devs, brain goetz or whatever that omniscient java guy is called who knows everything

late smelt
#

Allow me to break everyone with a single line

#
private final Set<ServerPlayer> trackingPlayers = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());```
surreal peak
#

why you gotta be so hard?

late smelt
#

Note: I have no idea if this even works

round fossil
# late smelt Note: I have no idea if this even works

Generally speaking, a doing this on a normal ConcurrentHashMap fucks it up hence why newKeySet() is encouraged, iirc MapMaker specifies by default a concurrency level of 4 achieving similar semantical implementation to a normal ConcurrentHashMap, I think caffeine the cache library does support a weak concurrent hash set tho

covert marsh
#

Nvm, it just generates a "main path" and then fills the rest with random stuff.

willow bone
#

like no looping back on itself, add shapes, starting and ending room are only on the walls, and some other complicated rules.

#

I'm curious as to if it would be possible with wave function collapse

covert marsh
willow bone
junior holly
surreal peak
#

calling a variable customItemEffects literally says nothing for me

#

also please make a lookup thing

junior holly
#

Elaborate please! (if you wouldn't mind <3)

surreal peak
#

also ItemStackCreation should be called ItemBuilder or smth

junior holly
#

Yeah my naming is meh for sure

surreal peak
#

like why do those things exist if its a builder

junior holly
#

Well the getCreatedItemStack is for some stuff elsewhere but yeah you're right

surreal peak
#

also cache that key

surreal peak
junior holly
#

Hmm alright

#

Anything else?

surreal peak
#

use kotlin

junior holly
surreal peak
#

well basically, and i see no reason to make it static

#

and List.of if you wanna go crazy

junior holly
#

Gotcha gotcha

terse spoke
#

Love some review on this framework I’ve started on a while back

#

Specifically on the framework as an external asset, and command & menu systems as a whole

woeful pasture
#

A lot of these utilities are nice but miss an edge to me. E.g. lack of component support. I think you should try and support components where you can we with spigot right now. And if you're willing to dip into nms support components on items etc

terse spoke
#

Component being the new string builder stuff with colors and that

surreal peak
#

cringe, use the scheduler

terse spoke
surreal peak
#

kinda, looks way better

terse spoke
#

yeah fair enough

#

any opinions on code structure, syntax, java as a whole

junior holly
#

I can definitely say the other way to run tasks looks cleaner

terse spoke
#

yeah gotchu

woeful pasture
terse spoke
#

menu practical system tho?

woeful pasture
terse spoke
woeful pasture
#

If you want ideas on something maybe a bit more powerful I have an api that uses 100% nms and I also have a partial nms one

round fossil
#

Ares singleton field should be named instance without capitalization its not a true constant, work more with implicit else/guard clauses, your function in PlayerUtils makes little sense, TimeUtils is bad you should favor DateTimeFormatter, prefer boolean state to unregistering a listener via its handlers, what’s the point of BoardAdapter - it doesn’t seem to follow the adapter design pattern thus misleading name, split ur execute() method in CommandData - its too long, not sure why you suffix ur Listener derivatives to Handler - its misleading since they do not handle the event its fine to name it something such as CommandListener; rather they just listen and observe it, avoid abstract classes when there’s much state and many abstract methods that derivatives need to implement it causes tight coupling

terse spoke
cobalt trellis
#
    @Nullable
    private ArtifactContentIndex generateArtifactContentIndex(@NotNull ProjectIndex project, @NotNull MavenVersion version) {
        NavigableMap<MavenVersion, Changeset> changesets = project.changesets.getReadView();

        Map.Entry<MavenVersion, Changeset> changeset = changesets.floorEntry(version);
        if (changeset == null) {
            return null;
        } else if (changeset.getValue() instanceof FullChangeset fullChangeset) {
            return fullChangeset.index;
        }

        MavenVersion currentVersion = changeset.getKey();
        while ((changeset = changesets.lowerEntry(currentVersion = changeset.getKey())) != null
                && !(changeset.getValue() instanceof FullChangeset));

        if (changeset == null) {
            throw new AssertionError(project + "; " + version + "; " + currentVersion + "; No full changeset encountered.");
        }

        ArtifactContentIndex aci = ((FullChangeset) changeset.getValue()).index;
        while ((changeset = changesets.higherEntry(currentVersion)) != null
                && !(currentVersion = changeset.getKey()).isNewerThan(version)) {
            aci = changeset.getValue().updateContents(aci);
        }

        if (changeset == null) {
            throw new AssertionError(project + "; " + version + "; " + currentVersion + "; changeset null.");
        }
    }

So people said I should nest less - are you happy now?

opaque plover
#

looks cool

#

what does this while loop do lol

dense leaf
#

????

#

tff

opaque plover
#

why isn't the function returning anything either in the end

#

ok what

dense leaf
#

that is

#

cursed

cobalt trellis
#

Well the return thing is caused by me forgetting a single line

cobalt trellis
#

The code probably has a few bugs - we'll see whenever I put it into production.
Jk, I'm writing unit tests for this

surreal peak
#

we all know that last line is a lie

cobalt trellis
#

Well the last line should be return aci; - but that is a bit obvious, innit?

cobalt trellis
#

Okay after a bit more of unit testing here's teh final result:

    @Nullable
    private static final ArtifactContentIndex generateArtifactContentIndex(@NotNull ProjectIndex project, @NotNull MavenVersion version) {
        NavigableMap<MavenVersion, Changeset> changesets = project.changesets.getReadView();

        Map.Entry<MavenVersion, Changeset> changeset = changesets.floorEntry(version);
        if (changeset == null) {
            return null;
        } else if (changeset.getValue() instanceof FullChangeset fullChangeset) {
            return fullChangeset.index;
        }

        MavenVersion currentVersion;
        while ((changeset = changesets.lowerEntry(currentVersion = changeset.getKey())) != null
                && !(changeset.getValue() instanceof FullChangeset));

        if (changeset == null) {
            throw new AssertionError(project + "; " + version + "; " + currentVersion + "; No full changeset encountered.");
        }

        ArtifactContentIndex aci = ((FullChangeset) changeset.getValue()).index;
        currentVersion = changeset.getKey();
        while ((changeset = changesets.higherEntry(currentVersion)) != null
                && !(currentVersion = changeset.getKey()).isNewerThan(version)) {
            aci = changeset.getValue().updateContents(aci);
        }

        return aci;
    }

Honestly, working with iterators is a fun exercise - especially when you're trying to produce code that is as unconventional as possible while doing so

jagged rock
#

if-return-elseif?

#

The else is unnecessary

wintry fern
#

should just be an else if anything

#

but they could just invert their condition instead

#

and just make it a single if

cobalt trellis
gilded gate
surreal peak
#

dont call your main class Main, call it FriendsPlugin or smth

#

also what does class Friend say to me? FriendsManager maybeµ

#

in your main class
private MySQL mySQL;
private Database database;
what??

#

use dependency injection instead of a static instance

dense leaf
#

?di ^-^

rich fogBOT
surreal peak
#

FriendAdd -> AddFriendCommand?

#

unchecked casts commandsender -> player

#

comparing player instances with ==, i mean not an issue perse

gilded gate
dense leaf
#

use the new instanceof syntax

surreal peak
#

not for your main class and mysql thing

surreal peak
#

id just use Arrays.asList of List.of ere

dense leaf
#

that is an absolutely useless arraylist right there KEKW

surreal peak
#

loadHashMaps() and saveHashMaps() is like a terrible name? saveData()?

#

what even does local mean in this context? make it more clear

#

MySql has a hard dependency on ConfigManager, maybe try to avoid that, try to pass that config manager as constructor param or pass in a ConfigurationSection?

surreal peak
#

how do i explain this uhh if you ever get rid of that config manager thing, your code will be kinda hard to refactor assuming you use that class directly everywhere

#

uhh

gilded gate
#

cause its static?

surreal peak
#

uh thats one thing

#

its also kinda fucked cuz all it does it provide YourPlugin::getConfig()

#

like hoping that file trick works

#

and String::replaceAll is for regex btw, you want ::replace (in that same class)

#

like is this what coloring means lol?

#

also not a big fan of exposing collections in your Friends class, you have em private but share em public either way, whats the point then

#

addFriend(), removeFriend() no?

#

this contains/ put call can also be optimized, putIfPresent
maybe even consider map::merge to replace that whole block but idk the exact parameters out of my head

#

and doesnt List::remove already return a boolean?

gilded gate
#

@surreal peak
playerFriends.merge(playerUUID, friends, (oldValue, newValue) -> newValue);

#

that works?

#

I updated it

#

please look now

jagged rock
#

put already overrides the previous value

#

So both calls are meh

#

Watch me be picky:

  • Utils:10 Single letter variable, should be renamed to something a bit more specific

  • FriendsPlugin:19 Poor / confusing ordering of methods, put your static getter at the bottom

  • FriendsPlugin:31 Repeated method calls, unscalable if-else chain. You should use some sort of database registry / provider pattern

  • FriendsManager:11,12 HashMap -> Map. Hide implementation details, If you decide to change the data structure later on, you have less to change

  • FriendsManager:29,33 Return a defensive copy of the map (Map.copyOf), otherwise the method that calls it can mutate the map at will.

  • FriendsManager:41,57 The friends manager shouldn't be responsible for sending a message. Use a return true/false for that.

  • JoinListener:11 Single letter variable, should be renamed to something a bit more specific. The entire class is pretty much useless but I get this is unfinished work.

  • DatabaseType:4 SQLite -> SQLITE, Follow naming conventions

  • MySQL:16,17,18,19,20 msqyl -> mysql. You should allow for the option to use a connection string

  • MySQL:47-60 This class shouldn't be responsible for creating the tables with your very specific structure. It's only responsible for managing a mysql connection

  • SQLite (the whole class) This class should be renamed because it doesn't represent an SQLite database, but rather a flat-file (yml). It also saves everything in a single file, which is AWFUL for performance and should NEVER be done. (If you have ~100k entries your server takes up to 5 minutes to load)

Not much to comment about your command system. It's really primitive and could use some better naming here and there

late smelt
#

Is Map.copyOf different from Collections.unmodifiableMap

jagged rock
#

Deep vs shallow clone iirc

pine grail
# jagged rock Deep vs shallow clone iirc

the former creates a new map under the following conditions:

  1. The map is not an immutable map
  2. The map is not empty

Then it simply makes a new array of the entries, the objects within are still the same but you can edit each map indepentently

#

the other is just an unmodifiable view over the underlying map

round fossil
#

1st one is so dumb since it assumes its gonna be that ImmutableCollections.ImmutableMap or sth