#help-development

1 messages · Page 2105 of 1

tender shard
#
            for(Player player : Bukkit.getOnlinePlayers()) {
                player.discoverRecipe(getRecipe(woodType).getKey());
            }
#

still doesn't show up

#

hm it shows up after rejoining

#

so yeah the group thingy works fine but discoverRecipe is still behaving weird unless you rejoin

kind hatch
#

Did you reload the server when loading that plugin?

tender shard
#

seems like "discoverRecipe" only tells the server "player got the recipe" but doesn't inform the client about it

kind hatch
#

Did you run /reload at any point during your testing?

tender shard
#

no

kind hatch
#

Odd. I've had a different experience when it comes to recipes. They just kinda show up when I add them.

flat olive
#

is there a method to get all permissions a user has when they join

#

instead of checking hasPermission

#

get all perms so I can drop them in my db

tender shard
#

getEffectivePermissions()

flat olive
#

ty

tender shard
#

that returns a Set<PermissionAttachmentInfo>

fading lake
#

depends on the vector

vocal tundra
#

any vector

tender shard
#

you're doing something wrong

#

what do you set the velocity to?

#

I bet setting it to 1,1,1 will work fine

#

you're probably setting it to some way too large thing

vocal tundra
#

sending it straight up with a magnitude of 1 - 2

tender shard
#

it works 100% fine

#
    @Override
    public void onEnable() {
        getCommand("test").setExecutor(new CommandExecutor() {
            @Override
            public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
                commandSender.sendMessage("Setting velocity to 0,1,0");
                ((Player)commandSender).setVelocity(new Vector(0,1,0));
                return true;
            }
        });
    }
vocal tundra
#

a spawned entity tho

#

I spawn wolf, then set velocity to (0, 1, 0) immediately

#

it goes up but then it immediately spikes down

#

for some reason

kind hatch
#

I think you need to apply velocity on the next tick if you are spawning mobs into existence.

tender shard
#

nope

#

you can do it directly

#

and it works fine

#
    @Override
    public void onEnable() {
        getCommand("test").setExecutor(new CommandExecutor() {
            @Override
            public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
                commandSender.sendMessage("Setting velocity to 1,1,1");
                Entity entity = ((Player)commandSender).getWorld().spawnEntity(((Player)commandSender).getLocation(), EntityType.ARMOR_STAND);
                entity.setVelocity(new Vector(1,1,1));
                return true;
            }
        });
    }
#

?paste your code pls

undone axleBOT
noble lantern
#

my code just worked the first time through perfectly and i dont know wether to be scared, concerned, or just accept it

echo basalt
#

it's probably bugged and you just don't know it

#

I always go "yay it isn't throwing an exception" and then I realize it isn't even being called anymore

noble lantern
#

Well like, im making an annotation that auto registers a command, and the command runs suprisingly

#

its gonna break sooner or later i feel it

#

it definatly can have 4 annotations, could add them as optionals

#

suprisingly the code for the reflection access to this was stupidly simple

#

havented tested dependency injection for JavaPlugin's though

#

im sure thats fucked

Edit: broken as shit gg

rugged cargo
#

where can i look for information about permissions?

noble lantern
rugged cargo
#

how they work

#

im trying make per player settings

tender shard
#

permissions are basically simply a Map<String,Boolean>

#

well not exactly but pretty much

tender shard
rugged cargo
#

as a starting point, see i used a word. it turned out to be the wrong word. oops

tender shard
#

what kind of settings do you want to store per player?

#

also do you need those settings to be accessible even when the player is not online?

rugged cargo
#

nope. basically just a boolean value as a well

tender shard
#

I'd just use the player's PersistentDataContainer

#

definitely the easiest way if you only need to store one boolean per player

quaint mantle
#

or metadata if its per-session

tender shard
#

yeah, do you need it to be persistent about rejoins / server restarts, or not?

rugged cargo
#

ideally it should stay forever

tender shard
#

then use the player's PDC

rugged cargo
#

ill be toggling the value via a command

tender shard
#
public boolean getPlayerSetting(Player player) {
        return player.getPersistentDataContainer().getOrDefault(settingsKey, PersistentDataType.BYTE, (byte) 0) == (byte) 1;
    }
    
    public void setPlayerSetting(Player player, boolean enabled) {
        player.getPersistentDataContainer().set(settingsKey, PersistentDataType.BYTE, enabled ? (byte) 1 : (byte) 0);
    }
#

we're using bytes here because spigot doesn't have a boolean type builtin

rugged cargo
#

ah. i didn't realize that you could cast directly to byte. that is extremely helpful

tender shard
#

oh also, the settingsKey is a NamespacedKey,where "this" is the main instance of your plugin:

private final NamespacedKey settingsKey = new NamespacedKey(this, "name-of-the-setting");
rugged cargo
#

i used that for recipes, so im good on that. but thanks anyways for this!

tender shard
#

np

rugged cargo
#

checking PersistentDataContainer#has() should be enough to ensure that i dont get null when using PersistentDataContainer#get() right?

sand vector
#

What event will trigger when a item is clicked by an item inside the inventory. I have a feeling it is InventoryInteractEvent but im unsure

crisp steeple
#

inventoryclickevent

sand vector
#

👍

tender shard
rugged cargo
#

oh. derp

tender shard
#

getOrDefault will return the given default value (in my case above, "(byte) 0") if it's not set

rugged cargo
#

i always do things the hard way. 🤦‍♂️

#

i feel like i should ensure every player have the key when they join though so that doesn't become a problem.. do you see anything wrong with that?

tender shard
#

just put your check whether they have it enabled into one method that always uses getOrDefault

#

but ofc you can also just save it to them onJoin, doesn't really matter

#

well

#

wait

#

it does matter

rugged cargo
#

right. ok, i guess it makes it less messy

tender shard
#

imagine the following situation:

#
  1. admins can decide whether the default value is "true" or "false" for new players
  2. a player joins. default is currently set to "false"
  3. "false" gets saved to that player
  4. admin changes default value to "true"
  5. the player will still have false now

If you use getOrDefault instead, the new "default" value will apply to everyone who never changed the value themselves.
If you set the value on join, the new "default" value will only apply to people who had never joined before

#

so it depends on what behaviour you'd rather like

rugged cargo
#

well it seems that if i use getOrDefault there is more of a possibility of using a config file to globally specify the default value

vocal tundra
#

I'm loving it

rugged cargo
#

which is good

#

and config files are good for admins as they are common amongst plugins already

tender shard
#

if you plan to add further config options later on, i'd probably directly store a yaml file in the PDC, or create a custom PDC data type for the player settings btw

rugged cargo
#

yeah, ok. getOrDefault has a lot going for it. i think thats what i should go with

tender shard
#

yeah that's what I'd use too

rugged cargo
#

lol. untintended consequence happened. but thats unrelated

#

but the fact that it happened means that my PDC value works

#

programmer error. obviously

tender shard
golden turret
#

how do i get the right sound for the given material

#

something like

#

Material.AIR.getSound()

tender shard
#

e.g. Bukkit.createBlockData(Material.DIRT).getSoundGroup()

golden turret
#

thanks

tender shard
#

then you can do getPlaceSound(), getStepSound() etc

golden turret
quaint mantle
tender shard
#

also why is his neck like half a meter

#

not my type

golden turret
#

he is chad

tender shard
#

some things are "kinda wrong":

#

first: give your variables proper name. "player" instead of "p"

#

second: do not blindly cast "cs" (which should be called "commandSender" or "sender" instead) to Player without checking if it actually is a player

#

it is shorter but you have tab-complete in your IDE

#

also imagine it's not a player, but an event that you call "e"

#

now 100 lines later, you wonder "is e an entity or an event or an exception"

#

but yeah you should use proper names although that's just a tiny thing I wnated to mention

#

third: you shouldn't check the command's name, but only register commandexecutors to the right command in the first place

#

you should actually never need to check "cmd.getName()"

#

fourth: this kinda code is pretty much duplicated:

            if(p.isFlying() || p.getAllowFlight()){       
                p.setFlying(false);
                p.setAllowFlight(false);
                p.sendMessage("§6Player flight is now disabled!");
                return true; 
        } else {
                p.setAllowFlight(true);
                p.setFlying(true);
                p.setFlySpeed(speed);
                p.sendMessage("§6Player flight is now enabled!");
                return true; 
            }

I'd do it like this: (1 min pls)

echo basalt
#

yeah that's uh

urban trout
#

how would i go about making a config.yml for my tab plugin

#

i have the main config set up

tender shard
#
                boolean isFlying = !player.isFlying();
                player.setFlying(isFlying);
                player.setAllowFlight(isFlying);
                player.sendMessage(isFlying ? "You are now flying" : "You are no longer flying");
                return true;
urban trout
#

just not sure how id get that to be as many lines as the user wants

tender shard
#

and fifth: You should not hardcode the § section sign for color codes, it might no longer work in future versions. Instead rather use ChatColor.translateAlternateColorCodes

echo basalt
#
boolean flying = player.isFlying() || player.getAllowFlight();

player.setFlying(!flying);
player.setAllowFlight(!flying);
player.sendMessage("§6Player flight is now " + (flying ? "dis" : "en") + "abled!");
quaint mantle
tender shard
echo basalt
#

whatever

#

you get the idea

tender shard
quaint mantle
sand vector
#

So when using PDC to store custom enchant data(name), do I use a PersistentDataType or String to hold the enchant and do this for each enchant I add?

tender shard
#

the "§" is implementation specific and so one shouldn't just assume it'll never change imho

#

I just mentioned it because they asked for improvement ideas

tender shard
quaint mantle
undone axleBOT
sand vector
#

So when I do Enum.valueOf I have the enum and then the string will be the name or the enchant?

tender shard
#

this'd be my suggestion:

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("This command is only available for players.");
            return true;
        }
        Player player = (Player) sender;
        float speed = 0.03f;

        // Not needed, just set the permission in plugin.yml
        /*if (!player.hasPermission("frostycore.pfly")) {
            player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4You do not have permission to use this command"));
            return true;
        }*/

        final boolean isFlying = player.isFlying() || player.getAllowFlight();
        player.setFlying(isFlying);
        player.setAllowFlight(isFlying);
        if(isFlying) player.setFlySpeed(speed);
        player.sendMessage(ChatColor.translateAlternateColorCodes('&', isFlying ? "&aYou are now flying." : "&cYou are no longer flying."));
        return true;
    }
urban trout
tender shard
urban trout
quaint mantle
#

that wiki

urban trout
#

but not with a set amount of lines

quaint mantle
#

has everything

#

you need to know, literally just read it

tender shard
urban trout
#

like a tab config

quaint mantle
#

literally just read the wiki

#
saveDefaultConfig();
List<String> header = getConfig().getStringList("header");
List<String> footer = getConfig().getStringList("footer");
tender shard
golden turret
#

how can i spawn the block break particles

#

this only spawns at the given location

#

not like the natural break

quaint mantle
#

generate some random

golden turret
#

wdym

quaint mantle
#

like add some random to the location

tender shard
#

the spawnParticle methods takes some floats or doubles for random offsets

quaint mantle
#

good to know

#

ive been writing abstractation for this plugin for 3 days

golden turret
#

?jd

quaint mantle
#

?jd-s

undone axleBOT
sand vector
tender shard
#

basically yeah, but normally enums have NAMES_LIKE_THIS

#

e.g. UNBREAKING, CURSE_OF_BINDING etc

#

I'd probably save an EnumMap<EnchantEnum,Integer> into the item's PDC

#

so e.g. you could store stuff like
UNBREAKING -> level 3
CURSE_OF_BINDING -> level 1
in the item meta

carmine mica
#

why are you creating a whole separate enum? the api already has a pseudo-enum for enchants

sand vector
#

for my own custom ones

tender shard
carmine mica
#

oh I didnt realize custom enchants were involved, I just saw UNBREAKING and CURSE_OF_BINDING and was like, those are vanilla

tender shard
#

I'd use a custom Enum for my enchantments and use my PDC lib to store them as a EnumMap on the itemmeta: https://www.spigotmc.org/threads/more-persistent-data-types-collections-maps-and-arrays-for-pdc.520677/

E.g.

EnumMap<MyCustomEnchantment,Integer> enchants = pdc.get(someKey, DataType.asEnumMap(MyCustomEnchantment.class, DataType.INTEGER));
tender shard
#

bukkit does that automatically

#
commands:
  test:
    description: Some command
    permission: some.permission.name
#

in plugin.yml

#

it knows that automatically since you use getCommand("test") to set the executor

#

and the permission is attached to the command using plugin.yml

#

i still don't know why you're checking the command's name

#

the command name will always be "pfly"

#

also your code style is weird

#

sometimes you do

if(statement) { // bracket on same line

and oher times you do

if(statement)
{ // bracket on next line
quaint mantle
#

you're missing the space from the if

tender shard
#

i never put spaces there

quaint mantle
#

disgusting creature

#

pretty sure its required in google codestyle

#

and what google says, you do!

tender shard
#

I don't work for gnoogle 😮

#

i'm fine with any style as long as the brackets are on the same line

hexed hatch
#

if (statement) { supremacy

#

space before and after the conditional or perish

tender shard
#

tbh I don't think it's worth to even think a second about this kind of stuff

#

just let intellij format the code before you push and everyone is happy

hexed hatch
#

Yeah well I think it’s all that matters

quaint mantle
#

based

hexed hatch
#

So we’re at an impasse

tender shard
#

let's fight about important stuff
like why are people comparing the command name in their command executors

quaint mantle
#

does this work, do not freaking try it and see me

public static final String PLUGIN_VERSION = "${project.version}";
#

maven

quaint mantle
#

got it

tender shard
#

but you can make it work

quaint mantle
#

how

tender shard
#

don't use /src/main/java

#

but

#

erm

#

sth similar

quaint mantle
#

its in the resources

#

it works in the resources

tender shard
#

it's something called generated-classes or so

#

one sec I have it in one project

#

put the classes into src/main/java-templates

#

then

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>templating-maven-plugin</artifactId>
  <version>1.0-alpha-3</version> <!-- Be sure to use the last version. Check on the website's plugin -->
  <executions>
      <execution>
      <id>filter-src</id>
      <goals>
          <goal>filter-sources</goal>
      </goals>
      </execution>
  </executions>
</plugin>
quaint mantle
#

too much work im good

tender shard
#

but it has some weird side effects so I stopped using it

#

easier way is to use a properties file to get that kinda stuff

#

since properties are filtered by default anyways

#

e.g. bukkit does it like that for Bukkit.getBukkitVersion()

#
    public static String getBukkitVersion() {
        String result = "Unknown-Version";
        InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties");
        Properties properties = new Properties();
        if (stream != null) {
            try {
                properties.load(stream);
                result = properties.getProperty("version");
            } catch (IOException var4) {
                Logger.getLogger(Versioning.class.getName()).log(Level.SEVERE, "Could not get Bukkit version!", var4);
            }
        }

        return result;
    }

this is from Bukkit's "Versioning" class

quaint mantle
tender shard
#

(no idea why it reads the file EVERYTIME - it should rather be cached on startup)

quaint mantle
#

BRUH

tender shard
#

yeah well

#

wellll

#

CraftServer itself caches it

sand vector
tender shard
#

so if you don't access Versioning yourself, it's fine

tender shard
sand vector
#

yeah I am

tender shard
#

okay then you can do something like this: (one second, let me write sth down quickly)

quaint mantle
#

i know of a method on how to

tender shard
#

@sand vector

tender shard
#

took me about a whole day to get collections, maps and arrays neatly working with EVERY PDC type

sand vector
#

So like this (Dw about naming I'll change it in a bit)

tender shard
#

example for a EnumMap<Material,Integer>:

#
    @Test
    void test() {
        EnumMap<Material,Integer> map = new EnumMap<>(Material.class);
        map.put(Material.DIRT, 1);
        map.put(Material.STONE, 2);
        
        // Save the map
        pdc.set(key, DataType.asEnumMap(Material.class, DataType.INTEGER),map);
        
        // Load the map again
        EnumMap<Material,Integer> savedMap = pdc.get(key, DataType.asEnumMap(Material.class, DataType.INTEGER));
    }
quaint mantle
#

too lazy to write the method

tender shard
#

I'd be interested in how you'd do it

sand vector
#

Thanks! That has saved a bit of my time working out how to do this 😅

tender shard
#

so basically I create two PersistentDataContainers, one holding the keys, another one holding the values. Both are mapped using integer indexes as namespacedkeys. Of course the actual Map datatype then doesn't simply accept the actual key/value type, but again a PersistentDataType<?,K> or <?,V>

quaint mantle
#

i dont understand that

flat olive
#

How would I set food level to whatever user the player enters for the second argument? /feed <Player>, I have the logic I just don't know how to make the second argument the player object, I also tried casting the arguments into player obj

quaint mantle
#

but if it works

tender shard
tender shard
#

will get the player whose name matches the first word entered after /feed

flat olive
#

ty

#

I also have a question

#

is the arguments at index 0 just /feed or is it index 1 for the second argument, player

quaint mantle
#

0 = first argument

#

just like arrays

flat olive
#

and first argument is the command right?

quaint mantle
#

no

#

in this case player

flat olive
#

oh I see

quaint mantle
#

command is its own variable, label or Command#getName()

flat olive
#

arguments are whatever is after

quaint mantle
#

right

flat olive
#

okay makes sense, thanks

#

if the command is typed and there are no arguments then is arguments null?

quaint mantle
#

nope its just an empty array

flat olive
#

Oh dang, okay then

quaint mantle
#

if (args.length == 0)

flat olive
#

Yeah that's what I got so far

tender shard
#

@quaint mantle

#

this is the result of this:

#
            @Override
            public boolean onCommand( CommandSender sender,  Command command,  String s,  String[] strings) {
                EnumMap<Material,Integer> map = new EnumMap<>(Material.class);
                map.put(Material.DIRT, 1);
                map.put(Material.STONE, 2);
                map.put(Material.GRASS, 3);

                Player player = (Player) sender;
                // Save the map
                player.getPersistentDataContainer().set(new NamespacedKey(Test.this,"test"), DataType.asEnumMap(Material.class, DataType.INTEGER),map);
                return true;
            }
#

(without the "chestsort" part ofc)

#

so "k:1" = key 1 = "DIRT", "v:1" = value 1 = 1 as integer

#

and so on

quaint mantle
#

weird

tender shard
#

well

#

how else would you do it

quaint mantle
#

i mean im pretty sure we got the same idea

tender shard
#

you have to imagine that both key and value could be ANYTHING, even an itemstack or whatever, so I'm not simply mapping stuff to a number but create basically a pair of "integer-based" pdc tags for every key and every value

flat olive
quaint mantle
#
Map<String, Integer> map = new HashMap<>();
map.put("hi", 5);
# PDC in YAML format

# PersistentDataType.STRING
namespaced-key-params: "String:Integer"

# PersistentDataType.TAG_CONTAINER_ARRAY
namespaced-key-entries:
#

ive gotten this far

tender shard
quaint mantle
#

this could go about serialization or trying to fuck with pdcs

#

serialization is better

#

so i'd just store strings tupled with their type

#

basically just json

#

in a pdc string

flat olive
tender shard
#

but what if you now wanna store something like a Map<ItemStack,LinkedHashMap<Material,Map<Integer,ItemMeta>>> @quaint mantle ?

quaint mantle
#

you do you

#

its your library, not mine

#

🙂

tender shard
#

I mean noone will ever need it but I wanted to use this to learn about generics so I wanted to make this work with EVERYTHING 😄

quaint mantle
#

good luck

tender shard
#

it's already done since 3 or 4 weeks

flat olive
tender shard
#

erm

#

yes

#

obviously

#

read your code line by line

#

you do this: "if no args were entered, get the first argument"

#

there obviously is no first argument if there is none

flat olive
#

oh

#

🤣

tender shard
#

/feed -> args.length == 0
/feed mfnalex-> args.length == 1

flat olive
#

I was told the first argument was what they typed after command🤷‍♂️

kind hatch
#

It is.

tender shard
#

yeah that's correct

#

args[0] is the "first" element of args

kind hatch
#

It is the first argument, but you have to remember that java uses zero based arrays.

flat olive
#

Yeah its the first index

kind hatch
#

So the first element of the array starts at 0 instead of 1

tender shard
#

{} = empty (0 elements)
{"mfnalex"} = 1 element, so the "biggest" index you can access is 0
{"mfnalex","someoneelse"} = 2 elements, so the "biggest" index you can access is 1

flat olive
#

ah I see I was confused

quaint mantle
#
      ["Bob", "Mary", "Joe"]
         ^      ^       ^
 INDEX   0      1       2
LENGTH   3
flat olive
#

I was thinking it was like that but then got confused because I thought the second arg was starting at 0,

#

Yeah Ik

#

you said player was 0

grizzled bridge
#
    @EventHandler
    public void onPlayerJoin(@NotNull PlayerJoinEvent event) {
        ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
        SkullMeta meta = (SkullMeta) skull.getItemMeta();

        meta.setOwningPlayer(Bukkit.getOfflinePlayer(UUID.fromString("e3b94eb5-2386-4e25-8cdf-c6652677b12b")));
        skull.setItemMeta(meta);

        event.getPlayer().getInventory().setItemInMainHand(skull);
    }

Whenever I do this, I get a default head

flat olive
#

/feed <player> player is actually 1

quaint mantle
#

no

#

player is 0

flat olive
#

/feed is 0

#

?

quaint mantle
#

no

tender shard
#

no...

#

args = ARGUMENTS

#

it's like this:

#

/<command> <arguments...>

#

just look at the onCommand method

flat olive
#

Okay so

kind hatch
#

The command is excluded from the arguments array. It's technically part of the array, but it's removed because of the implementation,

tender shard
#

it has

  1. the sender (player who entered the command)
  2. the command (e.g. "feed")
  3. the alias they used for this command (e.g. "feedplayer")
  4. the arguments, so everything they entered AFTER /<alias>
quaint mantle
#
/feed <some_arg>
  ^       ^
label     |
        args[0]
flat olive
#

oh my god

#

I was so confused

tender shard
flat olive
#

I forgot the length method starts at 1

quaint mantle
#

length is just like normal counting

flat olive
#

🤦‍♂️

#

I was so confused

#

I was like why is it out of range then

quaint mantle
#

you would love lua

tender shard
flat olive
#

actually I have checked that already above I just never realized it was working already

#

I forgot all about length starting at 1 🤣 my brain is dying tonight

grizzled bridge
#

Should I use a PlayerProfile then?

kind hatch
#

Or maybe it's the GameProfile

tender shard
#

you can use a base64 texture though

grizzled bridge
tender shard
urban trout
#

hello, got my config and scoreboard sorted but now how would i get the lines of my config into the according lines/score in the scoreboard

grizzled bridge
kind hatch
#

Offline skins are annoying. I swear older versions just worked when it came to this. Now, you have to make a GameProfile, make a request to mojang servers, populate said GameProfile with the results, then you can get the texture.

tender shard
grizzled bridge
#

wtf

tender shard
#

the PlayerProfile api is nice but also a bit weird

kind hatch
#

I think he wants to get actual player heads.

tender shard
#

e.g. you have to provide a link to the minecraft textures server

grizzled bridge
#

Im taking a look at your lib and this shit seems so complicated

grizzled bridge
#

UUID to head

urban trout
tender shard
urban trout
#

well objective is the title i think

#

score is like the main bit

#

with text n stuff

#

and scoreboard is like the board

tender shard
#

IIRC people mostly abuse the score to sort the lines

#

while objective is the actual text

urban trout
#

oh yeye

tender shard
#

e.g. a scoreboard like this:

Money: 37$            1
Your name: mfnalex    2

this scoreboard has two objectives, called "Money: XX$" and "Your name: mfnalex"

#

the score of the objectives are only used to sort the lines

grizzled bridge
#

@tender shard I'm confused, your lib uses offline players too?

tender shard
urban trout
#

so how would i like split up a list into different scores so its on different lines

tender shard
#

loop through your list of strings. e.g. imagine this is your list:

  • "first line"
  • "second line"
urban trout
#

ye

tender shard
#

create a new objective called "first line" and give it score 2
create a new objective called "second line" and give it score 1

grizzled bridge
tender shard
#

basically the top line has to have the highest score

urban trout
#

mhm

#

ok

#

how would i go about doing that

tender shard
kind hatch
#

The base64 string is just an encoded string that represents a texture.

grizzled bridge
#

Also why the random UUID?

kind hatch
#

That's for custom texture heads.

#

If you want a real player, just use their UUID.

tender shard
#

exactly. the random UUID is to not mess up profiles of players who are actually on your server

#

I still wonder - why do you need textures of players who never joined your server, if it's not meant to be a "custom" texture?

#

like e.g. you will never need the skin of "mfnalex" if I never joined your server. but obviously you might want to use a custom texture from minecraft-heads.com

#

so I don't really understand what you are actually trying to do

tender shard
#

at least that's how I understood it

grizzled bridge
kind hatch
grizzled bridge
#

its for a feature on my server

tender shard
urban trout
#

alright i have

for(String entry : Config.get().getStringList("scoreboard")){
}```
#

how would i get each line of the string

tender shard
grizzled bridge
#

YES

#

exactly

tender shard
urban trout
tender shard
# urban trout have what

you should definitely look at some basic java tutorials if you don't know how to loop over a list

urban trout
#

ye prolly

sand vector
#

Im back again. Im getting this error when compiling? Unsupported class file major version 60 Im guessing its my java version but I've also tried up to 18 and still have the issue

urban trout
#

i'll do that next school break

#

for now

#

back to my list

tender shard
kind hatch
sand vector
#

no maven-compiler-plugin

tender shard
#

click on the top most thing, the one I marked in red

#

then ?paste the full console output

#

because the "Unsupported class file" message can have many reasons

sand vector
grizzled bridge
#

@tender shard com.mojang.authlib.GameProfile Where do I get this import

tender shard
kind hatch
tender shard
#

one has to manually install it using mvn install:install-file

carmine mica
#

ok, well you don't have to manually install it. just add the mojang maven repo to your pom and the dependency that way

tender shard
#

oh yeah that works too, I didn't know they have a public repo

kind hatch
#

Are you sure? Because I don't even have that repo in my pom and GameProfile is just available to me.

carmine mica
#

if you are using nms you've got it too cause its a dependency for the server

kind hatch
#

That's what I was getting at.

tender shard
carmine mica
#

but the api doesnt depend on it

#

so you can add it if you dont want to depend on the server

grizzled bridge
carmine mica
kind hatch
#

I figured it was NMS as I noticed it was available with it before the mappings came along.

tender shard
kind hatch
#

I just so happen to always compile craftbukkit and have the remapped versions. 😛

tender shard
#

I got something mixed up in my head. It was those people who are NOT using maven who had to manually add the authlib as dependency

#

because of the whole "bootstrap .jar" stuff

tender shard
#

so you might have to add this too:

<pluginRepositories>
  <pluginRepository>
    <id>apache.snapshots</id>
    <url>https://repository.apache.org/snapshots/</url>
  </pluginRepository>
</pluginRepositories>
#

if you don't get it to work, ?paste your pom.xml

sand vector
#

I changed the "maven-shade-plugin" to 3.3.0 and it compiles and works!

tender shard
#

perfect

#

I wasn't sure whether 3.3.0 was already released

#

I still use 3.3.0-SNAPSHOT everywhere so that's why I mentioned the plugin repositry 😛

grizzled bridge
tender shard
#

use "spigot" as dependency instead of "spigot-api"

#

be sure to run buildtools first

grizzled bridge
#

imma be honest

#

i am extremely lost

#

what is buildtools

tender shard
#

?bt

undone axleBOT
grizzled bridge
#

thx

tender shard
#

buildtools is the tool that "builds"/compiles spigot on your PC

grizzled bridge
tender shard
#

as an alternative, you can just add my library to your dependency section, then you can directly use SkullUtils

kind hatch
#

Something that's been bugging me for a while. Why is it that my IDE gives this error, but still compiles? I have multiple java versions installed. (Java 8, 11, 16, and 17) My IDE is set to use the Java 16 SDK, I'm telling maven to compile against Java 8 and that the project source is Java 8. Yet, it still compiles successfully.

I'm testing the plugin on 1.18.2 so, I need java 16. I'm assuming that my jar file wouldn't actually work on a Java 8 server if it reached this line of code. Haven't tested that, but why is it compiling?

tender shard
#

switch to java 8 and it won't compile

#

your .jar would not run on java 1.8

#

btw you do not NEED java 16 for a 1.18 plugin

#

simply remove the charset and you get rid of that warning

#

or better

#

replace "StandardCharsets.UTF8" with a string "UTF-8"

lavish hemlock
#

StandardCharsets is Java 7, Alex

#

Actually wait no

#

java.nio.charset was added as early as Java 4

tender shard
#

it's not part of URLDecoder constructor in java 8

#

erm I mean

#

of the decode() method

grizzled bridge
tender shard
#

java 8 expects a String as charset in java 8 @lavish hemlock

#

java 16+ also stills accepts the string

#

so if they are compiling for java 8 anyway, they should also use the string

grizzled bridge
tender shard
#

either listen to me or go ask at paper's discord

grizzled bridge
#

banned 🥲

kind hatch
grizzled bridge
#

ill just figure it out myself

tender shard
tender shard
kind hatch
tender shard
#

I compile ALL my plugins for java 8, using only java 8 or earlier API, and that runs fine on java 17. java 17 can easily run java 8 code. it's just that minecraft itself now requires java 17 because the server itself uses some modern features

#

so yeah you should either not compile for java 8, or stop using java 10+ features 😛

kind hatch
#

Well, I'm trying to move past java 8, but I need to get a couple more updates out first before I can make the full transition.

tender shard
#

for now you can easily replace StandardCharsets.UTF_8 with either StandardCharsets.UTF_8.name() or simply replace it with a string "UTF-8"

kind hatch
#

Gotcha. It's weird having multiple versions installed. The new switch statement format prevented me from compiling, which I kinda expected, but this one was weird to me because, normally, when any type of error shows up, it just doesn't compile.

tender shard
#

yeah that's because you weren't using a new "language feature" with the Charset thingy

#

the new switch cannot be translated to a java 8 source file since that is a language feature only available in java 14+

#

but it's no problem to compile against a method that's not included in an older JDK

#

it would simply throw a NoSuchMethodError at runtime on java 8

#

but since you used java 16, it compiled fine, even to a java 8 class file

#

I can't find the proper words to explain it, I hope you get what I'm trying to say lol

kind hatch
#

I think it makes more sense now. It's just a little weird that you are allowed to do that.

tender shard
#

yeah well, it has to do with how bytecode works

#

the bytecode simply sees "get the method called "decode(String, StandardCharset)" and call it using the following params: ..."

#

javac is invoked using java 16 so it sees that method

#

so it's like forgetting to shade a library when you run that in java 8 then

#

but obviously calling a method is no different in java 8 than in java 16

#

that's why it compiles fine

kind hatch
#

That's something else that I'm wondering about though. I thought that the point of defining this

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
</properties>

In the pom would force compilation in the defined java version.

tender shard
#

oh no, if you look at your maven log, you'll see that it used java 16 or whatever you set in your IDE to call javac

grizzled bridge
tender shard
#

you can use paper all you want

#

doesn't mean you need it as dependency

#

you obviously don't listen to me anyway so feel free to seek help from someone else

tender shard
kind hatch
#

Yea, just looked at the log. It's using java 16.

tender shard
#

it does NOT make sure that all those methods are also there. after all, you could have compiled against a "runtime dependency" like spigot

#

obviously org.bukkit.craftbukkit.CraftServer is also not present in the JDK 8 but you can still compile your code, since the compiler has it as runtime dependency 🙂

#

and the JDK 16 compiler also had that method as "runtime dependency"

#

I can't explain it better right now, it's too late for that 😄

kind hatch
#

No worries. I get the gist of it. I also now understand what those flags actually do.

tender shard
#

:3

maiden thicket
flat olive
#

can someone tell me how to make [org.bukkit.permissions.PermissionAttachmentInfo@5c4ccb0d] PermissionAttachmentInfo show up as a string inside my db instead of the object name

#

I tried setting the object to a string, adding the object to an array, and multiple things I just don't know what will work now

maiden thicket
#

use gson methinks

#

what r u trying to do tho

flat olive
#

im trying to get all of a users permissions and store them in a database

#

however as a string

#

not the object

#
            Set<PermissionAttachmentInfo> playerPermissions = event.getPlayer().getEffectivePermissions();

maiden thicket
#

i think its better to store each permission node and its boolean value in a db

#

however if u really want to use permissionattachmentinfo just serialize using gson

rugged cargo
#

when doing Block#setType is there any kind of world update i need to do. or chunk update?

flat olive
#

I use getEffectivePermissions to get all permissions that a user has, I try to parse it but it doesn't work so how would I store each permission node

#

I might have just figured it out

#

yeah no lol it always outputs as

[org.bukkit.permissions.PermissionAttachmentInfo@333d287f, org.bukkit.permissions.PermissionAttachmentInfo@3c8e3f0d,
vocal tundra
crude charm
#

I quit development a while ago but I'm tempted to get back into it. However every time I've had this itch it's ended up in me leaving again due to burnout. Not to mention the fact that I've probs forgot 90% of everything I knew and no longer own a vps or anything like that. Is it worth it? Still considering

dense geyser
#

is there a packet for suggesting commands to players without them needing to click on a basecomponent with an inbuilt suggest feat?

spring pike
#

how can I check if a player is looking away from another player by at least 90 degrees?

lean gull
#

what's the event for when a player's main hand item is changed? like if they scrolled through their hotbar, or if the item broken, or if they swapped the item with another item, etc etc

spring pike
#

not sure which version tho

lean gull
#

thx

spring pike
#

np

kindred valley
#

can i input object by scanner?

grizzled bridge
#
        ItemStack playerHead = new ItemStack(Material.PLAYER_HEAD);
        UUID hashAsId = new UUID(base64.hashCode(), base64.hashCode());
        return Bukkit.getUnsafe().modifyItemStack(playerHead,
                "{SkullOwner:{Id:\"" + hashAsId + "\",Properties:{textures:[{Value:\"" + base64 + "\"}]}}}"
        );

Whats a non deprecated way of doing this?

chrome beacon
#

What version are you on

grizzled bridge
#

It's the lastest

chrome beacon
#

So 1.18.2

grizzled bridge
#

yessir

chrome beacon
#

To get skull meta simply cast ItemMeta

grizzled bridge
chrome beacon
#

Start by creating a PlayerProfile instance. Then get the PlayerTextures from it and use setSkin

grizzled bridge
#

Any chance you could run me through how to make a PlayerProfile instance?

chrome beacon
#

Use getTextures on the PlayerProfile and modify that

#

Then set it back again

grizzled bridge
#

Thats what I've been struggling with... I just have no clue how to do that and I've been digging in the docs for a bit

#

PlayerProfile is an interface though, how to I get an instance of one

chrome beacon
#

getTextures will return an instance of it

grizzled bridge
#

from the docs it appears to return a PlayerTextures object

chrome beacon
#

Didn't sent it ;/

grizzled bridge
#

lol

#

ahh

#

So something like

grizzled bridge
#

Bukkit.createPlayerProfile(UUID.randomUUID(), "")

#

then thats my PlayerProfile

chrome beacon
#

You can skip the empty name

#

Bukkit.createPlayerProfile(UUID.randomUUID()) exists

grizzled bridge
#

Now I have my PlayerProfile.. now what

chrome beacon
#

now call getTextures on it to get the texture instance

grizzled bridge
#

okie dokie

chrome beacon
#

Then you have the setSkin method to set the skin

#

If you only have base64 you will need to decode it and get the link to the skin

supple elk
#

that will give you the vector of the direction they're looking in I think

#

then just compare

#

do some trig

#

if you know the locations of the two players

spring pike
#

I know the locations of both players, just have no idea how to go on about it

supple elk
#

have you done trig before?

spring pike
spring pike
supple elk
#

use getEyeLocation if you want to get the direction they're pointing in I think?

supple elk
spring pike
#

i thought Eyelocation was the location of the camera, and getTargetBlock was the location where they're looking at?

supple elk
#

yes but .getDirection() on eyeLocation gives the direction they're pointing

spring pike
#

oh, okay

supple elk
#

you then know the locations between them, the distances, and the angles in which they are facing

chrome beacon
#

The result may end up as a json but it shouldn't be hard for you to get the texture link out of it

supple elk
#

by subtracting the distances between them

#

find the angle at which that vector is pointing

#

get the angle at which the player in pointing

#

compare

spring pike
#

that's a lot, but I'll try my best

supple elk
#

yeah it could be fairly challenging

spring pike
#

vector math is too much for me

supple elk
#

right

#

it's not too challenging

#

in a sense they're basically just co-ordinates

#

things do get slightly more complicated when you go into 3d tho

#

shouldn't File.pathSeparator be a \?

quiet ice
#

Path seperator is the seperator that is used between two paths

#

you likely want File.fileSeperator or something like that

#

actually idk

supple elk
#

ah ok

#

yeah File.separator gives '\'

#

typing backslashes is annoying lmao

quiet ice
#

Yep, that is it

#

And apparently google is down for me

native elbow
#

is there a way to overwrite the default world generator?

quiet ice
#

?jd-s

undone axleBOT
quiet ice
#

It is a whack API though, not sure what that method is doing in JavaPlugin

olive tapir
#

What can I do to Item getid

supple elk
#

anyone know why this happens?

#

it just dies

quiet ice
#

You need to escape the backslash

#

I assume

supple elk
#

how do I do that 🤔

quiet ice
#

Java version?

supple elk
#

17

#

and would this change depending on OS?

#

so do I only need to escape it if it's a backslash?

#

cause I don't think all OSs use a backslah

native elbow
quiet ice
sullen marlin
#

Pattern.quote

#

Or something

#

Yeah that's it

quiet ice
#

Yeah, that is probably a better way of doing it considering that not all java escapes are regex escapes

supple elk
#

thank you :>

sullen marlin
#

Idk what you're doing though

#

Using the path/file api to deal with folders makes more sense surely

quiet ice
#

Another way would be to use

Path path = dataFolder.toPath();
List<String> xyz = new ArrayList<>();
for (Path x : path) {
   xyz.add(x.toString());
}

If I am not mistaken

supple elk
sullen marlin
#

What are you trying to do

supple elk
#

so I'm making minigame worlds

#

I want to have them organised

#

so a folder for all maps

#

then sub folders for each game

#

then I need a folder for temp worlds

#

cause my plan is for when a minigames starts, I copy the world into the temp folder

#

so I can have multiple instances of the same world

#

then delete it when it's done

quiet ice
#

Then I am not sure why you need the split operation there.

supple elk
#

yeah probably not

#

I was having a look at this

#

which used splitting

#

but it doesn't look like a very good resource

#

I thought I'd just have a look anyway

#

so for something like this, how can I add to the end of it?

#

I'd like to create a new folder called 'maps'

granite owl
#

if i instantiate an inventory in a local scope like this ```java
Inventory inv = Bukkit.createInventory(null, 9*5, ChatColor.DARK_RED + "TEST");
inv.setContents(((Player)sender).getInventory().getContents());
((Player)sender).openInventory(inv);

midnight shore
#

Wdym GC?

granite owl
#

garbage collected?

#

or is the inventory deleted as soon as it gets out of scope and all opened instances are client sided?

midnight shore
#

Oooh in that sense

#

I think that the object will still be there even if nobody has it opened

granite owl
#

causing a memory leak

#

?

#

how do i properly close/delete/GC an inventory ive created myself in a local scale?

#

once the last inv viewer closes it

olive tapir
#

What can I do to Item getid help me please

spring pike
#

what do you mean with id?

olive tapir
#

iteminhand id

quiet ice
spring pike
olive tapir
granite owl
# quiet ice why would it not get GC'd after the inventory is no longer used?

becase i create an inventory in a local scale on command and let say the admin who has performed the command open the inventory right? then the inventory goes out of scale on exiting the command callback. yet the player still has an open instance of that inventory and its still passed to the InventoryClickEvent properly meaning even tho it went out of scope originally, its still existant.

quiet ice
#

As soon as an object is not reachable and does not have a finalizer block it will get GC'ed unless you are using the epsilon garbage collector

granite owl
#

so i wonder how to properly treat self created inventories so i dont cause a memory leak

spring pike
olive tapir
spring pike
#

ItemStack.getType()

glossy venture
#

ItemStack

quiet ice
quiet ice
granite owl
#

so its a safe method and the inv gets GC'ed as soon as the last inventory viewer is requesting the close inventory package?

quiet ice
granite owl
#

kk

quiet ice
#

Also your inventory even if it was to never get GC'd would only represent a tiny portion on the stuff that is actually leaking

spring pike
#

in newer minecraft versions there's a method to get the center of a block location, it's block.getLocation().toCenterLocation();
i can't find a way to get this in older versions tho, any help?

granite owl
chrome beacon
granite owl
#

and since certain methods in java are written low level accessing the system and user dll iirc

#

im never 100% certain

olive tapir
spring pike
#

if I understand you correctly, you're talking about an ItemStack
that would be the amount of the itemstack

granite owl
granite owl
#

memory clogging up

supple elk
#

If I have an abstract static field will each child class have their own version of the static field? My current understanding is that a regular static field will only exist once between inherited classes. For example child.staticField is equivalent to parent.staticField, but is this the case for abstract?

granite owl
#

u need to override abstract objects

#

u must

#

so no obv not

supple elk
#

👌

granite owl
#

u only create child + parent implementations when u dont override them

granite owl
#

and then u access them using this.foo() and super.foo() with super being the parental class @supple elk

olive tapir
spring pike
granite owl
#

and iirc abstract is forcing u to override them

spring pike
olive tapir
spring pike
#

because unless you're using worldedit or something like that, number ids are not used anymore, correct me if im wrong

chrome beacon
#

Numeric ids got removed in 1.13

#

And have been deprecated since 1.8

olive tapir
#

ohhh

spring pike
#

what would you need them for?

spring pike
#

no problem

quiet ice
supple elk
#

I'm trying to store metadata about a class. I have an abstract game class which all different games will implement, then a particular instance of a minigame will be one instance of a child class. I need metadata about each game class though, like the name of the game, display icon etc. Currently I have a static abstract field for each piece of meta data, however this is difficult to access when there is no specific instance of the class available. Any recommendations on how to do this?

#

for example:

#

I could do game.getField("name")

quiet ice
#

Game.name

supple elk
#

doesn't work

quiet ice
#

it does, it's static

supple elk
#

oh wait

chrome beacon
#

The real question is why is it static

glossy venture
chrome beacon
#

So remove static

supple elk
#

each child class needs to have a different val

glossy venture
#

just do getField() i guess

supple elk
quiet ice
#

that is kind of an antipattern

glossy venture
#

but make it protected static or something

#

or no access mod

supple elk
#

maybe a GameMeta object?

#

then link that to a class?

quiet ice
#

How many game instances should there be?

glossy venture
supple elk
#

any number

chrome beacon
#

Just have a getName method or smth and let each child class specify

quiet ice
#

If there is only one you might as well use a thread local :P

supple elk
#

yeah that's prob the thing

glossy venture
#

bruh i do it too

paper falcon
#

hey I've also got a question,
where should I put ChatColor.translateAlternateColorCodes() in here cuz wherever I do I get errors because the said method requires me to provide a string but I have an array list (lores from config).

ArrayList<String> lore = (ArrayList<String>) main.getConfig().getStringList("items.0.lore");
        assert meta != null;
        meta.setLore(lore);

https://prnt.sc/HUvdOzWi4Ugc

Lightshot

Captured with Lightshot

glossy venture
#

but then you dont need to register every event

#

to the event bus

supple elk
glossy venture
supple elk
#

cause I need to be able to access the method without an instance of the class

glossy venture
#

not on the instance

supple elk
#

yeah

quiet ice
#

There is no need for obtaining the handler list class that way anyways (well there is, but only because of strange API).

chrome beacon
#

uh reflection it is then I guess

supple elk
#

nah I can do this without

#

Map<Class<? extend Game>, GameMeta> ?

chrome beacon
#

oh well either way this sounds like a bad idea

quiet ice
#

MBassador for example can use ANY object as an event while still being able to use the object hierarchy

glossy venture
#

you can do it quite simply with

List<String> translatedLore = lore.stream().map(line -> ChatColor.translateAlternateColorCodes('&', line)).collect(Collectors.toList());
#

@paper falcon

supple elk
glossy venture
#

think that should work

chrome beacon
#

Same as I said

supple elk
#

I'm open to suggestions on how to structure it properly

chrome beacon
#

Just create an instance and get it

supple elk
#

but an instance of a game is a physical game in progress

quiet ice
#

Are you sure that you cannot create an instance of the class at that point?

supple elk
#

yes

#

in a menu I need to display which games exist

#

meaning I need to know the name of a game and a display icon

noble lantern
#

make a boolean of started and if its false the game isnt started

And then loop through the listof games and from there filter by true started booleans

#

boom, running games

paper falcon
quiet ice
#

Yeah then it is quite clear that you will have a "GameFactory" class that will be able to create games

glossy venture
#

np

noble lantern
#

^

glossy venture
noble lantern
#

annotations in java are fun

quiet ice
#

So like your game meta idea but it is the only way to create a game

glossy venture
#

and then you can just do

public abstract String getName();
supple elk
#

it shows the possible games

quiet ice
#

I only really use annotations for ASM Transforming these days or for event handling or for NotNull/Nullable and other contracts

supple elk
#

so for example say I have 3 different games, tnt run, survival games and skywars

#

there can be multiple instances of each

#

but I need to know the metadata about each without there being any instances

#

the name of the game, icon, etc

#

cause an instance is a physical game in progress

chrome beacon
#

Just use an instance

quiet ice
#
public interface GameFactory {
   public Game createGame();
   public String getName();
}
public interface Game {
   public GameFactory getFactory();
}

is how I would do it

chrome beacon
#

You will have them stored somewhere

noble lantern
#

havent really touched them too much beforehand

supple elk
chrome beacon
#

Not really

noble lantern
#

Its normally how you do things

#

you have a Manager of some sorts for your list of Game's

chrome beacon
#

If you want a list of running games, use the running games instance?

quiet ice
#

Either way, reflection is the wrong way of doing it

supple elk
supple elk
quiet ice
#

The other solution would be to have something like

public abstract class Game {
    private boolean started = false;
    private final String name;
    private static final Map<String, ? extends Game> games = new HashMap<>();
    protected Game(String name) {
        this.name = name;
        if (games.putIfAbsent(name, this) != null) {
             throw new IllegalStateException("There is already a game with that name");
        }
    }
    public boolean start() {
        started = true;
    }
    public boolean end() {
        started = false;
    }
    public String getName() {
        return name;
    }
    public boolean isStarted() {
       return started;
    }
    public static String getGameByName(String name) {
       return games.get(name);
    }
}
chrome beacon
#

Not sure if you really want to put things in the map directly in the constructor

quiet ice
#

I just did that to make sure that there aren't two game instances with the same name

granite owl
#

can i store objects in pdc?

tall dragon
#

if you serialize/deserialize them

granite owl
#

yea ik thats what i do

#

store them as byte array then

#

?

quiet ice
#

?jd-s

undone axleBOT
tall dragon
#

you could also do json

chrome beacon
quiet ice
#

?stash

undone axleBOT
granite owl
#

hm

quiet ice
#

It can also be an int-array and anything like that

supple elk
#

@quiet ice how is this?

#

so then if I want metadata I can call GameManager.getSkyWarsFactory.getMeta()

#

or getSkyWarsFactory.createGame() for a new game

quiet ice
# supple elk

I'd pass the factory instance through the game so it is a singleton

supple elk
#

slight issue with that

#

so if I have an abstract class or an interface for the Game class

#

what would the method declaration be?

#

cause I want Skywars to return a SkywarsFactory

quiet ice
#

yes, you can simple pass that factory through the contructor of skywars

supple elk
#

nvm I can do like this?

supple elk
# supple elk

but this method also needs to be static doesn't it?

solid cargo
#

is there any like minigame api?

supple elk
#

ughh why are abstract static methods not a thing

kindred valley
supple elk
#

cause the factory is the only thing which can get me an instance of the game

#

why is this so confusinngg

glossy venture
#

oh wait so Game is like the game type

supple elk
#

yes

glossy venture
#

oh

#

i thought it was an instance

supple elk
#

wait

steel swan
#

?paste

undone axleBOT
supple elk
#

no no Game is an instance

#

each child class which extends Game is a type of game

glossy venture
#

oh yea

supple elk
#

then an instance of a Game is a physical game itself

steel swan
glossy venture
#
public class Map {
  private final GameType type;

  public Map(..., GameType type) {
    this.type = type;
  }

  /* some function */ {
    String name = type.getName();
  }
}

public class Game {
  private final GameType type;
}

public class GameType<T extends Game> {
  private final Class<? extends Game> runtimeType;
  private final String name;

  public GameType(...) { /* do init */ }

  public String getName() {
    return name;
  }

  public abstract T createGame(...);
}
``` @supple elk something like this would work
supple elk
#

yeah that's pretty much what I have

#

The GameType is the Factory

glossy venture
#

ah ok

supple elk
#

Geol was suggesting that I get the GameType from the Game itself

#

but that doesn't seem possible

glossy venture
#

why call it factory tho

supple elk
supple elk
glossy venture
#

not all it does

#

it defines a game type

#

or like a game

supple elk
#

mk

glossy venture
#

doesnt matter tho

#

just do whatever

supple elk
#

do I need the runtimeType field?

#

I shouldn't do I don't think?

glossy venture
#

nah not really but it might be useful

supple elk
#

mk

#

it means I have to pass in the same info twice though

#

so I can't do Class<? extends Game?> runtimeType = G

glossy venture
#

no

#

for some reason

#

generics are not preserved

#

so they are gone at runtime

supple elk
#

type erasure

glossy venture
#

yeah

supple elk
glossy venture
#

yes

supple elk
#

I'm then using a singleton manager to store an instance of each factory

#

or gametype in this case

#

do you think an enum might be useful?

glossy venture
#

sure

#

nah i think static fields are best

#

well

supple elk
#

okay

glossy venture
#

nah

#

because you need abstract methods

supple elk
#

I think the system I have rn should work fine

glossy venture
#

yeah

supple elk
#

and yeah calling it GameType makes sense

#

rather than factory

glossy venture
#

also maybe store all running games in the game manager

supple elk
#

yeah exactly

#

that's my plan

glossy venture
supple elk
#

it does

#

If I'm passing it into the map

#

kinda weird to pass in a factory to the map or whatever

glossy venture
#

true

#

if youre going to make it available as an api or just want it to be clear i would use GameType yeah

supple elk
#

I mean I could make it as an API ig

#

I'm basically building all the foundational work atm to make minigames

#

I've done NPCS

glossy venture
#

nice

supple elk
#

a straight projectile

glossy venture
#

is it for a server

#

or like a public plugin

#

or minigame api

supple elk
#

My plan was just to make minigames to play with friends

glossy venture
#

ah

supple elk
#

but maybe I should separate API and implementation

#

hmm

#

there is one thing I don't like currently tho

#

which is that every new gameType I create I have to declare a new static field in the manager

glossy venture
#

its useful tho

#

you could also store them in a map

#

or list

#

and register them

supple elk
#

yeah

glossy venture
#

in your onEnable

supple elk
#

currently it's not gonna work as an API

#

as u have to add that static field into the class

granite owl
#

can i somehow create an inventory thats identical to creative/survival inventory a player opens when pressing E?

restive tangle
#

Don't think so

glossy venture
supple elk
#

but ur right it is very useful to have 🤔

glossy venture
#

but if you want commands like /creategame skywars you might want to store them in a map

supple elk
#

what would be the key?

restive tangle
#

What are you trying to implement?

supple elk
#

like the class of the Game?

restive tangle
#

No, just generally

supple elk
#

<<? extends Game>, GameType>

noble lantern
#

Will classes extending JavaPlugin get a Constructor called if they have one?

supple elk
restive tangle
#

Yes

glossy venture
#
public class GameType {
  // ...
  private final String id;
  
  public String getId() {
    return id;
  }
}

public class GameManager {
  private final Map<String, GameType> typesById = new HashMap<>();

  public void registerType(GameType type) {
    gamesById.put(type.getId(), type);
  }
}
#

smth like this

restive tangle
#

I guess you could use an enum

supple elk
#

ah ok

supple elk
restive tangle
#

Yes

supple elk
#

example plz

restive tangle
#

EnumClass.valueOf(name.uppercase)

#

/creategame skywars <-- name

supple elk
#

ah okay

#

so if this was an API