#development

1 messages · Page 36 of 1

little summit
#

package me.defusemc.kiteditor;

import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;

public class Main extends JavaPlugin implements Listener {
KitSelectGUI kitSelectGUI;
@Override
public void onEnable() {
Bukkit.getPluginManager().registerEvents(this, this);
getCommand("editkits").setExecutor(new KitSelectGUI());
getCommand("adddefaultkit").setExecutor(new KitEditorCommand());
kitSelectGUI = new KitSelectGUI();
kitSelectGUI.createInventories();
}
}

#

or should i replace @override with a eventhandler

#

i honestly think it might be one reason

edgy lintel
proud pebble
#

wouldnt it be better to check the player's y velocity and seeing if its 0?

edgy lintel
#

it might be issues other than the code

#

build versions etc? im not sure

#

the code doesnt seem to have any problems to me with a quick skim

#

try lowering the api version to your server version maybe

#

just saw it

little summit
#

It's 1.19.

edgy lintel
#

This server is running Paper version git-Paper-411 (MC: 1.17.1) (Implementing API version 1.17.1-R0.1-SNAPSHOT) (Git: 6625db3 on ver/1.17.1)

little summit
#

OH

proud pebble
#

according to your log the servers on 1.17.1

little summit
#

LMAOOO nvm then it's because my panel says 1.19.3

#

No idea why it hasn't updated

#

Thanks LMAO

edgy lintel
proud pebble
#

people actually develop plugins on servers that arent on their pc?

little summit
#

Yeah. Because this is for a MC server that people actually play on

proud pebble
#

uhhh, the question still stands?

#

like wouldnt it make sense to develop the plugin on a local test server so you can make sure all the features work before you push it to your production server?

edgy lintel
#

kinda makes sense for me
server owners usually have tons of money and they can afford a single testing server

and after finishing in semi prod server you can just enable the server right away
saving all the hassle

proud pebble
#

because ill tell you now, its much faster to update the plugin on a local server and reboot then it is to upload the plugin through ftp and reboot the cloud server

edgy lintel
#

i used to have potato pc so im quite used to waiting for remote reboots and uploading and all that

proud pebble
#

might aswell speed up the time to check every change

little summit
# proud pebble according to your log the servers on 1.17.1

[17:15:53 INFO]: [KitEditor] Enabling KitEditor v1.0.4
[17:15:53 ERROR]: Error occurred while enabling KitEditor v1.0.4 (Is it up to date?)
[17:15:53 INFO]: [KitEditor] Disabling KitEditor v1.0.4

still the same thing with the api version + the spigotmc dependency changed to 1.17.1

#

@edgy lintel any ideas?

torpid raft
#

is the .clone() necessary?

minor summit
#

add mutates the location

torpid raft
#

ah i would have figured it wouldnt

#

darn state

edgy lintel
little summit
#

I sent all of my code (the main class is outdated tho)

minor summit
#

i don't think that's particularly a lot, 0.5mspt means the server is doing almost nothing at all, it's only when tasks take more than 50ms when you start noticing lag and such

edgy lintel
# little summit I sent all of my code (the main class is outdated tho)

private final Inventory kitSelectInventory;
private final Inventory kitEditInventory;

Inventory inventory;

KitSelectGUI() {
    this.kitSelectInventory = inventory;
    this.kitEditInventory = inventory;
}

why are you assigning null inventory to a final inventory?
to assign to a final field, you have to assign a non null value to the field

maybe try creating the inventory first thru bukkiet.createinventory

#

code from kitselectgui

little summit
#

also is private even neccessary in my case

#

nvm

edgy lintel
little summit
#

u are right

#

done

#

is there anything else raising suspicions in the code?

edgy lintel
#
void createInventories() {
        // GUI for selecting the kit
        Inventory kitSelectGUI = Bukkit.createInventory(null, 6 * 9, ChatColor.translateAlternateColorCodes('&', "Edit Kits > Select"));

in createinventories you are declaring a new local variable in the function
maybe just remove the inventory from inventory kitselectgui so that it actually make changes to your kitSelectGUI variable in your class instead of local

little summit
edgy lintel
little summit
#

and do what with kitSelectGUI now

#

i got 7 errors Cannot resolve symbol 'kitSelectGUI'

little summit
#

when i fix the 7 errors i have bcuz wanderingpalace is telling me to do smth

little summit
proud pebble
little summit
#

sent

edgy lintel
# little summit <@292161924496490497>

no like make Inventory kitSelectGUI in createinventories refer to your kitSelectInventory in class

anyway its always great to keep all the modifiers like final out of your way when you are getting started with java

little summit
#

so I change it to:

Inventory kitSelectGUI = kitSelectInventory

edgy lintel
#

yes in function createinventories
and dont change the variable under the class

#

anyway lunaiskey should get your issues fixed
or if not the other people
i shall be off to sleep

little summit
#

For some reason I never got any errors other than the cant load

edgy lintel
#

yes and your remote server makes you from debugging harder 100x
you may want to load it in your local server first

#

or paper has messed with the error ouput

little summit
#

idk

proud pebble
#

you have a Main.class and a KitSelectGUI.class, they both extend JavaPlugin

little summit
#

when did

#

oh

#

damn.

#

So what should it extend instead

#

Oh commandexecutor i think

proud pebble
#

it shouldnt

little summit
#

so it shouldnt extend at all

proud pebble
#

theres nothing to extend

river solstice
#

is main section in plugin.yml optional?

river solstice
#

because from what you gave us it's missing

river solstice
#

oh

#

nvm, I'm blind

proud pebble
#
name: KitEditor
version: '1.0.4'
main: me.defusemc.kiteditor.Main
api-version: 1.17
authors: [ Axecy ]
description: Used for the FFA @ DefuseMC
website: dsc.gg/defuse
commands:
  editkits:
    description: Opens kit editor menu.
  adddefaultkit:
    description: Sets the default kit for a specific kit.
little summit
#

name: KitEditor
version: '${project.version}'
main: me.defusemc.kiteditor.Main
api-version: 1.17
authors: [ Axecy ]
description: Used for the FFA @ DefuseMC
website: dsc.gg/defuse
commands:
editkits:
description: Opens kit editor menu.
adddefaultkit:
description: Sets the default kit for a specific kit.

river solstice
#

I usually put it at the top line, that's why I thought it's missing

proud pebble
#

Main.class, ln 12 does nothing since theres no eventhandler methods in that class

little summit
#

ty

proud pebble
#

also please have one instance of each type of event that you want to use

river solstice
#

well, he changed it from

public class Main {
  onEnable() { register((Listener)this, this); }
}

to

public class Main {
  onEnable() { register(this, this); }
}

to

public class Main implements Listener {
  onEnable() { register(this, this); }
}

even though he has no handlers in the Main class 💀

proud pebble
#

imma assume this is the first time they have worked with the spigot api

#

tho also maybe the first time they are working with java in general

little summit
#

or im dumb and was tired working too early

river solstice
#

if you remove all the bs in your onEnable

#

does it work or not

little summit
#

idk, i'm gonna go check if it works now

proud pebble
#

you should name your main class something other then Main
you should only extend JavaPlugin once, and that being your main class
you should only have one instance of each type of event, and usually designate them to a listener class, because i guarantee funky behavior if you have multiple instances of an event

little summit
#

could you check my plugin rq if it works now cause i have no time atm to test

#

@proud pebble

proud pebble
#

it enabled

little summit
#

@proud pebble check if the commands work or not

#

./editkits

proud pebble
#

they dont spit out errors?

little summit
proud pebble
#

so i have time to do this but you dont?

little summit
#

i only want u do that

proud pebble
#

adddefaultkit works

little summit
#

alr

proud pebble
#

editkits doesnt

little summit
#

inventory is null

#

defo a NPE

proud pebble
#

ye

proud pebble
little summit
#

indeed. probably because i removed that from the KitSelectGUI class

#

gonna fix that, probably wont need help.

proud pebble
#

in every instance where you reference any Inventory they are never created

#

you just end up reusing the same null inventory

#

like theres no Bukkit.createInventory anywhere

little summit
#

createInventories() does exist however

proud pebble
#

it just references the inventory variable which never gets initalized

little summit
#

discord is bugging out for me, tried sending a file accidentally but now it won't let me type messages just tries sending a file

#

da

#

da

#

d

#

alr

#

fixed

#

um yeah it's because of wandering probably. he told me to change smth so i did to check

#

Fixed

proud pebble
#

also you shouldnt reuse the same inventory object

#

you should create a new one every time you want to open it

little summit
#

gonna go quickly make a 1.17.1 test server

proud pebble
little summit
#

i know

#

nah this is so annoying i aint even wanna test anymore at this point

#

java 18 isn't supported

proud pebble
little summit
proud pebble
#

1.17.1 uses java 16

#

when compiling your plugin you gotta make sure that you are compiling using a version that it supports

#

i usually either compile against java 11 or java 14,

little summit
#

im talking about paper

little summit
proud pebble
#

or atleast i thought it did

#

it does support up to java 17, its what im using

dense drift
#

It does support 17, 1.17 requires at least 16

proud pebble
#

tho i dont think it supports java 18, or atleast i know of people who have had issues booting with java 18 and above versions

dense drift
#

Just download jdk 17 and run with that

proud pebble
#

yeah

#

i personally use the adoptium binaries

dense drift
#

If you run the server through IDEA, you can download the jdk through it as well and just tell it what version to use, it takes like 4 clicks

little summit
dense drift
#

The java cmd uses whatever you have set in JAVA_HOME

#

But you can use a certain version by using the path to that jdk instead of the java cmd

little summit
proud pebble
little summit
#

18

#

it says

proud pebble
#

yep thats the problem

little summit
#

so i dont have 17 or smth?

#

cause istg ive downloaded it before

proud pebble
#

you can have multiple versions of java installed

#

but you can only have one JAVA_HOME variable, so its been set to the java 18 one

dense drift
#

Downloading a zip with the jdk won't make windows know you want to use that version instead of the other unless you tell it to

#

If you have the resources, run the server through IDEA as I said

proud pebble
#

instead of putting java in your start script/bat, you can reference the java.exe's location

little summit
#

java -Xmx3048M -jar server.jar -o true
PAUSE

this is what i have

proud pebble
#

for instance, "C:\Users\PC\.jdks\corretto-17.0.3\bin\java.exe" instead of java

little summit
#

how could I check in the command prompt where mine is installed

proud pebble
#

you find it manually

little summit
#

ah

proud pebble
#

the default location when installing adoptium for me was in my user folder

#

wait, why dont i have any roles?

#

shouldnt it have given me Tier III?

minor summit
#

lol

proud pebble
#

and i cant see dev-general now, ree

#

any idea how i go about getting this fixed?

minor summit
#

@robust crow

little summit
#

wtf weird u had tier 2 now nothing

proud pebble
#

i leveled up

minor summit
#

no you levelled down

dusky wolf
#
    public long getRemainingProtectionTime(Player player) {
        if (protectionTimeLeft.containsKey(player.getUniqueId())) {
            Plugin plugin = Bukkit.getPluginManager().getPlugin(getPlugin());
            assert plugin != null;

            // Creates a new Bukkit runTaskTimer runnable
            new BukkitRunnable() {

                // Gets the remaining protection time from the config file.
                int remainingTime = (Integer.parseInt(Objects.requireNonNull(getConfig().getString("protection_time_after_exiting_town_border"))));

                @Override
                public void run() {
                    protectionTimeLeft.put(player.getUniqueId(), remainingTime);
                    this.remainingTime--;
                    if (remainingTime == 0) {
                        protectionTimeLeft.remove(player.getUniqueId());
                        cancel();
                    }
                }
            }.runTaskTimer(plugin, 20, 20);
        }
            return protectionTimeLeft.getOrDefault(player.getUniqueId(), 0);
        }```

```java
    @EventHandler
    public void ExitTownBorder(PlayerExitsFromTownBorderEvent event) {
        // Gets a player's UUID.
        UUID uuid = event.getPlayer().getUniqueId();
        System.out.println("Player just exited the town border");

        // Adds a player's UUID to the protectedPlayers list when exiting a town.
        protectedPlayers.add(event.getPlayer().getUniqueId());

        // Gets the remaining time from the config file
        int remainingTime = (Integer.parseInt(Objects.requireNonNull(getConfig().getString("protection_time_after_exiting_town_border"))));

        // Runs a Bukkit scheduler to remove the player from the protectedPlayers hashmap
        BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, new RemoveProtectedPlayerTask(uuid), remainingTime*20L);

        // Adds the Bukkit task to a hashmap to cancel it when a player enters a town.
        removeProtectedPlayerTask.put(uuid, task);

        protectionTimeLeft.put(uuid, remainingTime);

        System.out.println("protectedPlayers after adding player: " + protectedPlayers);
    }```


``protectionTimeLeft.put(uuid, remainingTime);`` will send the player's uuid and remainingtime when exiting a town and then ``getRemainingProtectionTime`` should get it and start reducing the time with ``this.remainingTime--;`` until it reaches 0 and then remove the uuid from the hashmap and cancel the task then return the ``protectionTimeLeft`` so that the placeholder can parse how many seconds a player has left but for some reason it doesn't decrease it at all. For example: https://imgur.com/nZLMxcn

If anyone knows what's wrong it would help, been stuck on that part for nearly 2 days
proud pebble
#

so expireTime = System.currentTimeMillis() + (protectionInSeconds * 1000)

#

then you can just check whenever if System.currentTimeMillis() >= expireTime

#

if its not then return, if it is then you can do your code and at the same time just remove the uuid from the map

#

also dont do Plugin plugin = Bukkit.getPluginManager().getPlugin(getPlugin());

#

if you need to get the plugin instance you should pass through the main class instance through the constructor of the class your using it in

dusky wolf
#

im new at java

#

only been coding for 6 days

#

but already got around 90-100 hours of coding

signal grove
#

15 hours a day grind

dusky wolf
#

ye

#

I sleep at like 10am every day lmao

#

so I got tons of time to learn

#

hopefully I’ll be able to become good in a few months

#

even though it will probably take 1 year+ to fully get good

past ibex
#

meaning that tasks will begin overriding each other

dusky wolf
#

oh

past ibex
#

idk why you would schedule a task in a getter, that's an antipattern

#

getters shouldn't really change the state of the program, it will make things harder to debug

dusky wolf
#

I see

past ibex
#

also you could combine the lists of protectedPlayers and protectionTimeLeft if you want

#

as you can check the keys in removeProtectedPlayerTask with .containsKey, less data redundancy is also easier to debug since if data is only stored once, you won't have conflicting data

dusky wolf
#

hmm I actually don't need anything about protectedPlayers in that

#

since it's basically just gonna be a placeholder that's gonna return how long they got protection time left

#

(basically I'm gonna use that to create a bossbar later and make it so when a player exits the town border he gets the bossbar)

signal grove
#

im doing about the same thing as you, just instead of protectedPlayers its taggedPlayers

#

(it's a combat tag plugin)

#

it's a HashMap<Player, Long>, where long is the expiration time of the tag

dusky wolf
#

oh are you adding a placeholder?

#

to get the remaining time left?

signal grove
#

yes i just did

dusky wolf
#

oh I just can't figure it out tbh haha

#

I've been trying to do it for almost 2 days

signal grove
#

the logic or hooking into placeholder api

#

or both

dusky wolf
#

logic

#

I used this

#

private final Map<UUID, Integer> protectionTimeLeft = new HashMap<>();

signal grove
#

and then what, schedulers to decrement the time for each player?

#

that will work too, itll just have a lot of schedulers

dusky wolf
#

did this for now

#
package com.agaloth.townywild.hooks;

import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.agaloth.townywild.TownyWild.plugin;

public class TownyWildPlaceholderExpansion extends PlaceholderExpansion {
    private final Map<UUID, Integer> protectionTimeLeft = new HashMap<>();

    public TownyWildPlaceholderExpansion() {
    }

    public long getRemainingProtectionTime(Player player) {
        if (protectionTimeLeft.containsKey(player.getUniqueId())) {
            protectionTimeLeft.get(player.getUniqueId());
        }
        return protectionTimeLeft.get(player.getUniqueId());
    }

    public long setRemainingProtectionTime(Player player) {
        if (protectionTimeLeft.containsKey(player.getUniqueId())) {
            long expireTime = System.currentTimeMillis() + (5 * 1000);

            // Creates a new Bukkit runTaskTimer runnable
            new BukkitRunnable() {

                // Gets the remaining protection time from the config file.

                @Override
                public void run() {
                    protectionTimeLeft.put(player.getUniqueId(), (int) expireTime);
                    if (System.currentTimeMillis() >= expireTime) {
                        protectionTimeLeft.remove(player.getUniqueId());
                    }
                }
            }.runTaskTimer(plugin, 0, 20);
        }
        return 0;
    }```
dusky wolf
dusky wolf
signal grove
#

you should only store the expiration time once

#

and only call the scheduler once

dusky wolf
#

protectionTimeLeft.put(player.getUniqueId(), (int) expireTime);

#

isn't that storing it once

signal grove
#

it's put inside the runTaskTimer function, which is called every second

#

instead, you should set the protection expire time of the player once (outside the runnable), then make a call to runTaskLater(protection_duration) [not runTaskTimer], which removes the playey from the hashmap

dusky wolf
#

so runTaskTimer isn't needed for the placeholder right?

signal grove
#

correct

#

in your onPlaceholderRequest

dusky wolf
#
    @Override
    public String onRequest(OfflinePlayer player, String identifier) {
        if (identifier.equals("countdown")) {
            long remainingProtectionTimeInSeconds = getRemainingProtectionTime((Player) player);
            if (remainingProtectionTimeInSeconds > 60) {
                long remainingProtectionTimeInMinutes = TimeUnit.SECONDS.toMinutes(remainingProtectionTimeInSeconds);
                return Long.toString(remainingProtectionTimeInMinutes) + " minutes";
            } else {
                return Long.toString(remainingProtectionTimeInSeconds) + " seconds";
            }
            }
            return "";
        }
}```
signal grove
#

you can get the current time and subtract it from the expire time stored in the hashmap

dusky wolf
#

this is what I had

signal grove
#

then itll return protecttionTimeLeft.get(player) - currentTimeMs()

#

although if you take that approach, you should rename "protectionTimeLeft" to something more honest, like "protectionExpirationTime"

#

since protectionTimeLeft implies you're doing a countdown

dusky wolf
#

but would that update the placeholder every second though

signal grove
#

the placeholder request just answers when it's called. in order to "refresh" it, that's gonna be done by a scoreboard plugin or whatever

dusky wolf
#

yeah I was trying to get it working without one

#

I mean chatgpt got it working before but I deleted all the code since I want to learn how

signal grove
#

what i mean is, your plugin will respond instantly whenever it is called

dusky wolf
#

oh

signal grove
#

the reason scoreboard "lag" is because they don't constantly call it

#

they usually have a refresh rate to reduce unnecessary calls

dusky wolf
#

yeye but I'm not using a scoreboard in that case

#

it's only for the bossbar

#

since the placeholder & bossbar only shows when exiting a town border

signal grove
#

ah, yeah then just set the bossbar however often you want, it's probably fine to do it every half a second or so

dusky wolf
#

so if the placeholder was in the scoreboard it would constantly show 0 unless someone exits the town

signal grove
#

yes

#

you can also return something else if theyre inside the town

#

for example, when combat expires for my plugin, i return "Safe"

#

so it counts down to 0, then displays safe

dusky wolf
#

i see

dusky wolf
#

still can't figure it out tbh lmaoo

#
public class TownyWildPlaceholderExpansion extends PlaceholderExpansion {
    public static Map<Player, Long> protectionExpirationTime = new HashMap<>();

    public TownyWildPlaceholderExpansion() {
    }

    public long getRemainingProtectionTime(Player player) {
        return protectionExpirationTime.get(player.getPlayer());
    }

    public long setRemainingProtectionTime(Player player) {
        long expireTime = System.currentTimeMillis() + (5 * 1000);

            // Creates a new Bukkit runTaskTimer runnable
            new BukkitRunnable() {

                @Override
                public void run() {
                    protectionExpirationTime.put(player.getPlayer(), expireTime);
                    if (System.currentTimeMillis() >= expireTime) {
                        protectionExpirationTime.remove(player.getPlayer(), expireTime);
                    }

                }
            }.runTaskLater(plugin, 5*20);
        return expireTime;
    }```
#
    @Override
    public String onRequest(OfflinePlayer player, String identifier) {
        if (identifier.equals("countdown")) {
            long remainingProtectionTimeInSeconds = getRemainingProtectionTime((Player) player);
            if (remainingProtectionTimeInSeconds > 60) {
                long remainingProtectionTimeInMinutes = TimeUnit.SECONDS.toMinutes(remainingProtectionTimeInSeconds);
                return Long.toString(remainingProtectionTimeInMinutes) + " minutes";
            } else {
                return Long.toString(remainingProtectionTimeInSeconds) + " seconds";
            }
            }
            return "";
        }
}```
#

but then that will just cause a nullpointerexception

#

even though it shouldn't be null

signal grove
#

the method named "getRemainingProtectionTime" is not an accurate name, it gets the expiration time.

#

getRemainingProtectionTime should instead return protectionExpirationTime.get(player.getPlayer()) - System.currentTimeMs()

#

wait

#

why does the method player.getPlayer() exist

#

it just returns itself??

dusky wolf
#

to get the player

#

because the map has Player, Long

#

so I had to return a player

signal grove
#

oh i see, it returns the offlineplayer

dusky wolf
#

yeye

signal grove
#

nvm, thats fine

dusky wolf
#

but then if I use player

#

Operator '-' cannot be applied to 'org.bukkit.entity.Player', 'long'

#

it will say this

signal grove
#

your parenthesis are not surrounding the right thing, im guessing it says

// This is what i guess you have
return protectionExpirationTime.get(player.getPlayer() - System.currentTimeMs());
// Should be this
return protectionExpirationTime.get(player.getPlayer()) - System.currentTimeMs();
dusky wolf
#

nono with player.getPlayer() this doesn't happen

#

it only happens if I put player instead of player.getPlayer

signal grove
#

can i see the method

#

i dont believe that will produce those results

dusky wolf
#

let me send the whole class

#

one sec

#

posting on github

signal grove
#

you can also use

#

?paste

neat pierBOT
#
FAQ Answer:

Paste Services
When asking for help with a config/menu/code issue please use our paste bin:
(we prefer it over pastebin.com)
HelpChat Paste - How To Use

dusky wolf
#

ah yeah but it's easier to see if you need to check other classes for some reason

signal grove
#

it gives me no syntax error

#

i just threw it into my class, ignore the rest of the junk in there

dusky wolf
#

oh

#

oh nvm it works idk what I did wrong but I probably didn't pay enough attention idk

#

sorry about that one

signal grove
#

no problem

#

your onRequest method looks like it will work fine at a quick glance

dusky wolf
#
        at com.agaloth.townywild.hooks.TownyWildPlaceholderExpansion.getRemainingProtectionTime(TownyWildPlaceholderExpansion.java:23) ~[TownyWild-1.00.jar:?]
        at com.agaloth.townywild.hooks.TownyWildPlaceholderExpansion.onRequest(TownyWildPlaceholderExpansion.java:110) ~[TownyWild-1.00.jar:?]
        at me.clip.placeholderapi.replacer.CharsReplacer.apply(CharsReplacer.java:119) ~[PlaceholderAPI-2.11.2.jar:?]a:923) ~[Towny-0.98.6.0.jar:?]
        at me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(PlaceholderAPI.java:71) ~[PlaceholderAPI-2.11.2.jar:?]]
        at me.clip.placeholderapi.commands.impl.local.CommandParse.evaluateParseSingular(CommandParse.java:118) ~[PlaceholderAPI-2.11.2.jar:?]
        at me.clip.placeholderapi.commands.impl.local.CommandParse.evaluate(CommandParse.java:58) ~[PlaceholderAPI-2.11.2.jar:?]-Pufferfish-56]
        at me.clip.placeholderapi.commands.PlaceholderCommandRouter.onCommand(PlaceholderCommandRouter.java:114) ~[PlaceholderAPI-2.11.2.jar:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[pufferfish-api-1.19.3-R0.1-SNAPSHOT.jar:?]NAPSHOT.jar:?]
        ... 23 moreergames.bukkit.util.BukkitTools.fireEvent(BukkitTools.java:318) ~[Towny-0.98.6.0.jar:?]
←[m     at com.palmergames.bukkit.towny.listeners.TownyPlayerListener.onPlayerMoveChunk(TownyPlayerListener.java:901) ~[Towny-0.98.6.0.jar:?]```
#

return protectionExpirationTime.get(player) - System.currentTimeMillis(); still seems to return null

dense drift
#

yeah, you can not do a math operation on a null value

dusky wolf
#

I mean I just don't understand why it's null

signal grove
#

the player is not added to the map

#

first off, you should probably use protectionExpirationTime.getOrDefault(player, System.currentTimeMillis())

#

instead of just .get()

#

then it will return 0 if the player isn't added to the hashmap

#

second you need to find why the player isnt being added when you want them to

dusky wolf
#

maybe it doesn't get data from anywhere else?

signal grove
#

where in the code do you put the player and expiration time into the hashmap

dusky wolf
#

since in TownyWildTownEventListener I don't add anything to the map

#

protectionExpirationTime.put(player, expireTime);
if (System.currentTimeMillis() >= expireTime) {
protectionExpirationTime.remove(player, expireTime);

#

I would say here

dense drift
#

well then how do you expect it to have any data jeb_shrug

signal grove
#

hmm, is that still part of the runnable method

dusky wolf
#

yeah

#

maybe

#

I can add protectionExpirationTime.put((Player) protectedPlayers, (long) remainingTime);

#

in TownyWildTownEventListener when players exit a town border

#

protectedPlayers is a set

dense drift
#

no you can not do that

dusky harness
#

So much casting

#

Be careful

dusky wolf
#

it's so confusing

#

and hard at the same time

signal grove
#

what is protectedPlayers meant to be

#

oh i understand

#

there is no need for that set, since you store the players as keys to your protectionExpirationTime hashmap

dusky wolf
#

hmm

#

but what I don't get is how the placeholder is gonna know when a player exits the town

#

if I don't do that

signal grove
#

in the towny event listener, there should be a single player included as part of the event

#

you can get that player, and then add them to the hashmap

dusky wolf
#

single player included as part of the event I don't get that part tbh

signal grove
#

sorry i said that badly

dusky wolf
#
    @EventHandler
    public void ExitTownBorder(PlayerExitsFromTownBorderEvent event) {
        // Gets a player's UUID.
        UUID uuid = event.getPlayer().getUniqueId();
        System.out.println("Player just exited the town border");

        // Adds a player's UUID to the protectedPlayers list when exiting a town.
        protectedPlayers.add(event.getPlayer().getUniqueId());

        // Gets the remaining time from the config file
        int remainingTime = (Integer.parseInt(Objects.requireNonNull(getConfig().getString("protection_time_after_exiting_town_border"))));

        // Runs a Bukkit scheduler to remove the player from the protectedPlayers hashmap
        BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, new RemoveProtectedPlayerTask(uuid), remainingTime*20L);

        // Adds the Bukkit task to a hashmap to cancel it when a player enters a town.
        removeProtectedPlayerTask.put(uuid, task);

        protectionExpirationTime.put((Player) protectedPlayers, (long) remainingTime);

        System.out.println("protectedPlayers after adding player: " + protectedPlayers);
    }```
#

this is what I had

#

in the exittownborder event

signal grove
#

yes, event.getPlayer()

dusky wolf
#

oh

#

I see so I have to do this instead

#

protectionExpirationTime.put(event.getPlayer(), (long) remainingTime);

dense drift
#

int remainingTime = (Integer.parseInt(Objects.requireNonNull(getConfig().getString("protection_time_after_exiting_town_border"))));
there's getInt btw

signal grove
#

^ getConfig().getInt("protection_time....")

dusky wolf
#

idk getString was working so I left it that way

#

scared to break it again LMAO

#

it took me 1 entire day to get it working

signal grove
#

put comment on that line, and then try changing right below so it will still be there in case getInt doesnt work lol

dusky wolf
#
  • it won't work probably
#

Required type: String
Provided: Integer
no instance(s) of type variable(s) exist so that Integer conforms to String

signal grove
#

i know itll work, but thats just for your own sake

#
int remainingTime = getConfig().getInt("protection_time_after_exiting_town_border");
dusky wolf
#

oh bruh yeah

#

that's so much simpler

signal grove
#

are you using intellij btw

dusky wolf
#

yeah

signal grove
#

i honestly dont know half the spigot api, i just look at tab completes to guess things. it can be helpful to see what methods are included in getConfig(), etc.

dusky wolf
#

ah

#

that seems to completely break my protection system

signal grove
#

what did

dusky wolf
#

nvm I wonder what actually broke it

#

gotta look into that ig

#

okay

signal grove
dusky wolf
#

so protectionExpirationTime.put(event.getPlayer(), (long) remainingTime); breaks it

#

like instead of having 5 seconds of protection

#

it runs BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, new RemoveProtectedPlayerTask(uuid), remainingTime*20L); instantly

signal grove
#

the method should be empty besides those two things

dusky wolf
#

but now the placeholder actually returns something

#

probably have to change something since it takes currentsystemmillis

#

oh nvm

#

it returns currentsystemmillis as default value

#

when exiting the town it returns 5 seconds but stays at 5 seconds

#

I would guess it's because it doesn't get decremented

signal grove
#

it doesnt need to decrement

#

your getRemainingTime left uses currentTimeMs

#

are you using papi parse?

dusky wolf
#

yep

signal grove
#

can i see the towny exit event

dusky wolf
#
    @EventHandler
    public void ExitTownBorder(PlayerExitsFromTownBorderEvent event) {
        // Gets a player's UUID.
        UUID uuid = event.getPlayer().getUniqueId();
        System.out.println("Player just exited the town border");

        // Adds a player's UUID to the protectedPlayers list when exiting a town.
        protectedPlayers.add(event.getPlayer().getUniqueId());

        // Gets the remaining time from the config file
        int remainingTime = (Integer.parseInt(Objects.requireNonNull(getConfig().getString("protection_time_after_exiting_town_border"))));

        // Runs a Bukkit scheduler to remove the player from the protectedPlayers hashmap
        BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, new RemoveProtectedPlayerTask(uuid), remainingTime*20L);

        // Adds the Bukkit task to a hashmap to cancel it when a player enters a town.
        removeProtectedPlayerTask.put(uuid, task);
        protectionExpirationTime.put(event.getPlayer(), (long) remainingTime);

        System.out.println("protectedPlayers after adding player: " + protectedPlayers);
    }```
signal grove
#

ok, so there's still a bunch of things that may or may not be conflicting with it

#
@EventHandler
    public void ExitTownBorder(PlayerExitsFromTownBorderEvent event) {
        System.out.println("Player just exited the town border");

        // Gets the remaining time from the config file
        int remainingTime = getConfig().getInt("protection_time_after_exiting_town_border");

        // Add player to the hashmap storing expiration times.
        protectionExpirationTime.put(event.getPlayer(), (long) remainingTime);

        // Runs a Bukkit scheduler to remove the player from the protectedPlayers hashmap
        BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, () -> removePlayerIfExpired(player), remainingTime*20L);
    }

public void removePlayerIfExpired(Player player)
{
  // Remove the player if the time has expired
}
#

i've just deleted it all to make it simpler

#

the bottom method is where youll actually do the removing from the hashmap

dusky wolf
#

I'm using another class to remove the player tho

#
package com.agaloth.townywild.tasks;

import com.agaloth.townywild.utils.Messaging;
import com.palmergames.bukkit.towny.object.Translatable;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;

import java.util.UUID;

import static com.agaloth.townywild.listeners.TownyWildTownEventListener.protectedPlayers;

public class RemoveProtectedPlayerTask implements Runnable {
    private UUID uuid;
    private Player player;

    public RemoveProtectedPlayerTask(UUID uuid) {

        this.uuid = uuid;
        this.player = Bukkit.getPlayer(uuid);
    }

    @Override
    public void run() {
        // Removes a player from the protectedPlayers hashmap.
        protectedPlayers.remove(uuid);

        // Sends a message to the protected player telling them that their protection has ended.
        Messaging.sendMsg(player, Translatable.of("player_protection_ended"));
    }
}
#

RemoveProtectedPlayerTask

signal grove
#

you're using that to remove it from the protectedPlayers set

dusky wolf
#

yeah

signal grove
#

which is not the same as the hashmap

dusky wolf
#

but that one works as intended

#

it's just the placeholder not getting the amount of seconds correctly

signal grove
#

the placeholder is using the hashmap, not the set

dusky wolf
#

ohh

#

wait I don't understand, what is actually wrong

#

I'll add comments to remember

#

(sorry to bother you though, I'm pretty sure it's annoying to help especially for this)

signal grove
#

the set doesn't serve a purpose though

#

(that's why i removed it from the exit town border listener)

dusky wolf
#

I see

#

let me try

#

so I don't actually need
public void removePlayerIfExpired(Player player)
{
// Remove the player if the time has expired
}

#

since the RemoveProtectedPlayerTask will run

signal grove
#

no, the opposite

#

you don't need the RemoveProtectedPlayerTask, because you can implement that method to remove from the hashmap

dusky wolf
#

ohh

signal grove
#

for reference, my plugin looks like this, where the tagPlayer() method is basically your ExitTownEvent listener

#
    public void tagPlayer(Player player)
    {
        int duration = plugin.getConfig().getInt("tag-duration");
        if (!plugin.expirationTime.containsKey(player))
        {
            player.sendMessage(ChatColor.RED + "You have engaged in combat. Do not log out!");
        }
        long expireTime = System.currentTimeMillis() + duration * 1000L;
        plugin.expirationTime.put(player, expireTime);
        Bukkit.getScheduler().runTaskLater(plugin, () -> untagPlayerIfExpired(player), duration*20L);
    }

    public void untagPlayerIfExpired(Player player)
    {
        if(plugin.expirationTime.containsKey(player))
        {
            long expireTime = plugin.expirationTime.get(player);
            long now = System.currentTimeMillis();
            long timeLeftMs = expireTime - now;
            if(timeLeftMs <= 0)
            {
                untagPlayer(player);
            }
        }
    }

    public void untagPlayer(Player player)
    {
        plugin.expirationTime.remove(player);
        player.sendMessage(ChatColor.GREEN + "You are no longer in combat.");
    }
dusky wolf
#

hmm

#
    @EventHandler
    public void ExitTownBorder(PlayerExitsFromTownBorderEvent event) {
        System.out.println("Player just exited the town border");

        // Gets the remaining time from the config file
        int remainingTime = getConfig().getInt("protection_time_after_exiting_town_border");

        // Add player to the hashmap storing expiration times.
        protectionExpirationTime.put(event.getPlayer(), (long) remainingTime);

        // Runs a Bukkit scheduler to remove the player from the protectedPlayers hashmap
        BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, () -> removePlayerIfExpired(event.getPlayer()), remainingTime*20L);
    }
    public void removePlayerIfExpired(Player player)
    {
        // Removes a player from the protectedPlayers hashmap.
        protectedPlayers.remove(uuid);

        // Sends a message to the protected player telling them that their protection has ended.
        Messaging.sendMsg(player, Translatable.of("player_protection_ended"));
    }```
signal grove
#

(everyone else looking at it ignore the bad design)

dusky wolf
#

doing this will instantly remove the player from the set

#

instead of waiting 5 seconds (in that case)

signal grove
#

hmm

dusky wolf
#

I think it's because the RemoveProtectedPlayerTask implements a runnable

#

and this doesn't

signal grove
#

this is a runnable actually, its just simplified with () ->

dusky wolf
#

also should the protectionExpirationTime display something now

#

because it doesn't matter if I go in or out of the town

#

it will say 0 seconds

signal grove
#

does it print both messages out instantly?

dusky wolf
#

it prints Messaging.sendMsg(player, Translatable.of("player_protection_ended")); instantly yeah

signal grove
#

immediately

dusky wolf
#

mhm

signal grove
#

hmm

dusky wolf
#

I tested to see if it was only the message

#

but the protection also ends instantly

signal grove
#

oh

#
        // Gets the remaining time from the config file
        int remainingTime = getConfig().getInt("protection_time_after_exiting_town_border");

        // Add player to the hashmap storing expiration times.
        protectionExpirationTime.put(event.getPlayer(), (long) remainingTime);
#

you set the expiration time to remainingTime

#

instead of remainingTime*1000L + System.currentTimeMs()

dusky wolf
#

now it parses 27924408847 minutes

#

maths are hard lmaoo

signal grove
#

this must be an error on the getRemainingTime method then

dusky wolf
#

well it would say 27924408847 seconds

#

but since it's more than 60 seconds

#

it just replaces "seconds" by "minutes"

signal grove
#

the stored time is in milliseconds

#

so in your getRemainingTime method, you need to subtract it from System.currentTimeMs(), then divide by 1000, then (if larger than 60), divide by 60

river solstice
#

I have a time formatter class written up somewhere, you can pass ms or seconds and it will return a string like 1h 15m 40s

#

If you need

dusky wolf
#

was there an easier way without using currenttimemillisecond?

#

the math is too complicated

#

I'll give it a shot

river solstice
#

It's not complicated

dusky wolf
#

i mean I struggle to even do 7+5 quickly with mental math

#

my math skills are literal shit

river solstice
#

You likely havent had calculus 1 and calculus 2, you have no right to say that's difficult kek

dusky wolf
#

I had (or not)

river solstice
#

😌

dusky wolf
#

I finished high school

#

idk if that's calculus, I finished last year but I don't remember any of the classes I had tbh

#

but I passed by chance (and mainly because teachers were annoyed of me failing for 2 years in a row)

river solstice
#

Yeah well I studied both of those from top to bottom, and it was pain

#

In university, not highschool

dusky wolf
#

ah yeah

#

not doing uni lmaoo

#

high school was too hard already

#

'System.currentTimeMillis() - 5000 / 1000 / 60' can be replaced with 'System.currentTimeMillis()'

#

hmm

#

ohh nvm

#

(System.currentTimeMillis() - 5000) / 1000 / 60);

#

hmm nvm

#

that doesn't work too

#

This is what I did

#
    public long getRemainingProtectionTime(Player player) {
        return protectionExpirationTime.getOrDefault(player, (System.currentTimeMillis() - 5000) / 1000 / 60);
    }```
#

to see the current millis

#

and try to create a formula out of that

#

I guess that'll work

#

(System.currentTimeMillis() + 5000 - System.currentTimeMillis()) / 1000);

dusky wolf
#

it's because of int remainingTime = getConfig().getInt("protection_time_after_exiting_town_border");

#

replacing it by int remainingTime = (Integer.parseInt(Objects.requireNonNull(getConfig().getString("protection_time_after_exiting_town_border")))); fixes it

#

it's because getInt probably returns 0

#

instead of taking the config file's set seconds

#

protection_time_after_exiting_town_border: '5'

signal grove
#

ahhhh i understand

#

the issue is because you store the data as a string

signal grove
#

no quotes

#

then you can go back to regular getInt

signal grove
dusky wolf
#

yeye

#

I was testing out

#

but it still keeps returning 0 seconds after exiting the town border

signal grove
#

ok so youve

  • removed the quotes around the 5 from the config
  • are using getConfig().getInt()
dusky wolf
#

yep

signal grove
dusky wolf
#

oh wait

#

it's getting back to quotes

#

I'll have to change something rq

#

one sec

signal grove
#

oh! i see what happened here

#
public long getRemainingProtectionTime(Player player) {
        long now = System.currentTimeMillis();
        long expireTime = protectionExpirationTime.getOrDefault(player, now);
        long secondsRemaining = (expireTime - now) / 1000;
        return secondsRemaining;
    }
#

your parenthesis were unbalanced

#

to make it easier to understand, i broke it into several lines

dusky wolf
#

ohh

signal grove
#

just a note: this returns seconds remaining, not milliseconds

#

im not sure if you need milliseconds anywhere

dusky wolf
#

hmm

#

that returned -1675466582 seconds

#

maybe

#

long secondsRemaining = (expireTime - now) / 1000;

#

now - expireTime

#

instead of expireTime - now

signal grove
#

no, expireTime should be first

#

assume it is in the future, and now we have not reached it yet

dusky wolf
#

hmm okay

signal grove
#

where are you calling it from, just the onRequest?

dusky wolf
#

yeah

#
    @Override
    public String onRequest(OfflinePlayer player, String identifier) {
        if (identifier.equals("countdown")) {
            long remainingProtectionTimeInSeconds = getRemainingProtectionTime((Player) player);
            if (remainingProtectionTimeInSeconds > 60) {
                long remainingProtectionTimeInMinutes = TimeUnit.SECONDS.toMinutes(remainingProtectionTimeInSeconds);
                return Long.toString(remainingProtectionTimeInMinutes) + " minutes";
            } else {
                return Long.toString(remainingProtectionTimeInSeconds) + " seconds";
            }
            }
            return "";
        }
}```
signal grove
#

that looks good

dusky wolf
#

protectionExpirationTime.put(event.getPlayer(), (long) remainingTime*1000L);

#

that should be good as well normally

#

which would return 5000

signal grove
#

yeah that's fine.

#

is the current setup updated on github

#

i think itll be easier to see multiple files to fix this

dusky wolf
#

nono I'll update now

#

the two classes should be updated now

signal grove
#

ah

signal grove
#

this problem is still in effect

#

basically you set the expiration time to 5000, when it should be set to 5000 + System.currentTimeMillis()

#

then you subtract it from another big number later, making it negative

dusky wolf
#

are you talking about this one?

#

long expireTime = System.currentTimeMillis() + (5 * 1000);

#

oh nvm

#

it works!!!

#

Thanks a lot man!

signal grove
#

nice! no problem

dusky wolf
#

I was literally about to smash my monitor LMAO

signal grove
#

haha

dusky wolf
#

been trying to fix this for 20+ hours

signal grove
#

ah something to note though

dusky wolf
#

yeah?

signal grove
#

i didnt mention this earlier because i wanted the rest to work first

#

this method

public void removePlayerIfExpired(Player player)
    {
        // Removes a player from the protectedPlayers hashmap.
        protectedPlayers.remove(uuid);

        // Sends a message to the protected player telling them that their protection has ended.
        Messaging.sendMsg(player, Translatable.of("player_protection_ended"));
    }
#

you should make sure that the time has actually expired

dusky wolf
#

wdym

#

oh I see

signal grove
#

or what happens when a player re-enters a town while theyre under protection: the expiration will be set to a later time, but the first runTaskLater will still try and remove it from the hashmap earlier than expected

dusky wolf
#

the message gets sent 5 seconds later

#

but the protected player doesn't seem to do anything

#

and they can hit still during those 5 seconds

#

but I prob know the issue

#

it might be the uuid

signal grove
#

in your damage event, youre checking the set instead of the hashmap

#

it is best to delete the set's definition, then re-handle everywhere it shows an error using the hashmap instead

dusky wolf
#

oh okay

#

oh so I have the replace protectedPlayers by protectionExpirationTime

signal grove
#

yes, for instance in your PlayerDamagePlayer listener,

if (protectedPlayers.contains(victim.getUniqueId())) {

becomes

if (protectionExpirationTime.containsKey(victim)) {
#

if you delete your set where it is first defined, it will show an error in all the places that need to be removed / replaced by the hashmap

dusky wolf
#

yeye

#

ah yeah it works perfectly now!

#

thanks a lot honestly

#

I'll add tons of comments to not forget about it

signal grove
dusky wolf
#

yeye just tested it

#

works as intended

#

oh wait I see one problem actually

signal grove
#

for example:

  • set the config remaining time to 20 seconds
  • walk out of town
  • walk back in after 10 seconds, then immediately leave again

the hashmap's expiration time is now set to 20 seconds after the second exit, but the original task timer is still set to remove it after the first 20 seconds

dusky wolf
#

since the RemoveProtectedPlayerTask class isn't here it doesn't cancel the task when entering a town

signal grove
#

yes exactly

dusky wolf
#

// Gets the Bukkit task and cancels it.
if (removeProtectedPlayerTask.containsKey(uuid)) {
removeProtectedPlayerTask.get(uuid).cancel();
}

#

it was this line but idk if there a way to cancel it now

#

I'll check

#

hmm

#

since protectionExpirationTime's hashmap doesn't have bukkittask I can't cancel it

signal grove
#

right

#

you can make another hashmap that stores the latest bukkit task for each player

#

then when you leave the town, cancel any current task, and add the new one to the hashmap

#

im actually doing that now for my own plugin, since i have the issue too

dusky wolf
#

hmm I gotta find a way with this

#

BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, () -> removePlayerIfExpired(event.getPlayer()), remainingTime*20L);

#

since that's what was changed pretty much

signal grove
#

yes, so you have already gotten it in the 'task' variable

#

now you can check: if the hashmap already contains a task for that player, cancel it before setting the new one

#

here is what i do (again everyone ignore my poor placement of the hasmap inside the plugin)

#
        BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, () -> untagPlayerIfExpired(player), duration*20L);
        if(plugin.expirationTasks.containsKey(player))
        {
            plugin.expirationTasks.get(player).cancel();
        }
        plugin.expirationTasks.put(player, task);
#

where expirationTasks is a HashMap<Player, BukkitTask>

dusky wolf
#

ah yeah I was just doing that

signal grove
#

are you experienced with other programming languages besides java btw

dusky wolf
#

no

#

first time ever coding

#

(been coding for 6 days ~100 hours)

signal grove
#

im surprised you can at least understand the issues (even if you cant solve them alone), it takes most people a lot longer

dusky wolf
#

oh that's because of the comments pretty much

#

that's how I mainly learn

#

just put everything I code in comments

#

but those things I don't get them

#
        if (cancelProtectionTask.containsKey(event.getPlayer())) {
            cancelProtectionTask.get(event.getPlayer().cancel);
        }```
#

like this

#

where .cancel doesn't exist

#
        BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, () -> removePlayerIfExpired(event.getPlayer()), remainingTime*20L);
        cancelProtectionTask.put(event.getPlayer(), task);```
#

even though I put the task and the player on the hashmap

signal grove
#

cancel()

#

not cancel

dusky wolf
#

yeye ik

#

oh bruh

#

I forgot a paranthesis

#

LMAO

#

cancelProtectionTask.get(event.getPlayer()).cancel();

#

instead I was doing

#

cancelProtectionTask.get(event.getPlayer().cancel();

signal grove
#

ah

dusky wolf
#

always so confusing haha

#

I always think that my code is broken when things like that happen

#

and I start changing the code instead

signal grove
#

yeah

spark skiff
#

Is anyone able to help me with this?

forest jay
#

https://paste.helpch.at/gutoqeqase.md, I havent gotten many of these errors in the past, and not sure what to make of it. I am trying to paste something when the player leaves the game. I am using WorldEdit for the pasting. I can share code if you want as well.

#

Does anyone have some ideas to what could be causing my issues? They just started appearing, but I didnt make any changes to the schematic loading/unloading system.

#

Would the chunks not being loaded by players cause any issues?

spark skiff
forest jay
minor summit
#

how large is the schematic

forest jay
#

oh actually

#

it pastes one like 500x500

#

and a 30x30, although the small one shouldnt be causing issues

spark skiff
#

You might want to use FastAsyncWorldEdit

minor summit
#

eeh

forest jay
# spark skiff Using inventories yes

if I were you, I would check for when the item is clicked, and then send them a new inventory with the updated lore. At least that is how I would imagine it is done. I use a custom library (RedLib) that changes how things are ran.

#

There might/probably is a better way

spark skiff
#

Right, that's what I have currently, however its a huge mess with zero abstraction

forest jay
#

I mean, you could track the selection in a variable, and then run a method to open the GUI, and then when they click, you just change the variable and then run the method again.

#

unless that is what your doing

spark skiff
#

Should the variable be a string?

forest jay
#

it depends on the use case

#

if you are tracking settings, all you have to do is change the settings, and then check for their settings in the open gui method

#

if it is something that stays in the class, you can use a string, enum, integer, whatever works best for the data type.

spark skiff
#

I guess to rotate selections I could remove an item from a list and re-add it back?

forest jay
#

yeah, if you had for example three selections, you could have a list of selections, and then have an integer for the current selection, then just cycle the integer, and look for its correlated selection

spark skiff
#

I see

forest jay
#

There are a lot of ways to achieve what you are looking for, whatever floats your boat

dusky wolf
#

For some reason the placeholder doesn't get parsed when creating a bossbar (it gets parsed in commands though)

    @EventHandler
    public void ExitTownBorder(PlayerExitsFromTownBorderEvent event) {
        // Gets the remaining time from the config file
        int remainingTime = (Integer.parseInt(Objects.requireNonNull(getConfig().getString("protection_time_after_exiting_town_border"))));

        // Gets the player's uuid
        Player player = Bukkit.getPlayer(uuid);

        // Add player to the hashmap storing expiration times.
        protectionExpirationTime.put(event.getPlayer(), (long) remainingTime*1000L + System.currentTimeMillis());

        // Runs a Bukkit scheduler to remove the player from the cancelProtectionTask hashmap
        BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, () -> removePlayerIfExpired(event.getPlayer()), remainingTime*20L);
        cancelProtectionTask.put(event.getPlayer(), task);

        // Runs a Bukkit scheduler to update the bossbar progress and adds the player to the runningBossBars hashmap to remove it when entering a town.
        BukkitTask updateProgress = new UpdateBossBarProgress(event.getPlayer()).runTaskTimer(plugin, 20, 20);
        runningBossBars.put(event.getPlayer(), updateProgress);

        // Translates the %townywild_countdown% placeholder and gets the text, color and style from config files
        String bossBarText = PlaceholderAPI.setPlaceholders(player, getConfig().getString("bossbar_message","You are protected for %townywild_countdown%!"));
        String bossbarColor = getConfig().getString("bossbar_color");
        String bossbarStyle = getConfig().getString("bossbar_style");

        // Adds color support to the bossbar text
        bossBarText = ChatColor.translateAlternateColorCodes('&', bossBarText);

        // Shows the bossbar to the player
        timeLeftBar.addPlayer(event.getPlayer());

        // Sets the title to bossBarText with the translated %townywild_countdown% placeholder
        timeLeftBar.setTitle(bossBarText);
        timeLeftBar.setColor(BarColor.valueOf(bossbarColor));
        timeLeftBar.setStyle(BarStyle.valueOf(bossbarStyle));
    }```
#

Does anyone know why String bossBarText = PlaceholderAPI.setPlaceholders(player, getConfig().getString("bossbar_message","You are protected for %townywild_countdown%!")); doesn't parse my placeholder?

#

(I checked with the command and it's parsing it correctly but with the bossbar it just says 0 seconds)

river solstice
#

yall still on this 💀

dusky wolf
#

I'm done almost haha

#

I fixed everything

#

this is the last bug

#

now I'm just trying to fix this last bug so I can go to sleep LMAO

#

it's almost 12pm

#

Here is a visual representation of what I meant

#

the placeholder works perfectly, the bossbar just doesn't parse it for some reason

signal grove
#

Im working on combat plugin and I want to disable certain commands while the player is in combat. Right now I get the command that the player typed in the preprocess event, then use getPluginCommand().getName() to get the main command (if it's an alias). It always annoyed me that big plugins like worldguard blocked-cmds and essentials socialspy cmds don't do this for aliases, but maybe they have a reason that I'm unaware of. Any potential issues?

proud pebble
signal grove
#

right, thatll break it

#

thanks

#

ill just say if the plugincommand is null, then just directly compare it to the list of blocked commands

#

and whoevers doing the config will just have to write out all the aliases if it's not registered

proud pebble
#

yep thats what most do

signal grove
#

still, kinda annoying that those two plugins i mentioned don't do it, so you need to write out all the 600 aliases of essentials teleport commands

#

xD so unnecessary

dense drift
#

Yup, essentials is trash

#

Easy fix is to remove them from plugin.yml 🤣

proud pebble
#

essentials has way too many aliases

dense drift
#

and 3/4 of them don't make any damn sense

proud pebble
#

tho tp is usually a staff command

#

im still waiting to get my role fixed lol

signal grove
#

yeah i mean teleporting in general, spawn, warp, etc. all have these garbage aliases

#

and to block them in combat... most combat tag plugins need you to write out all of the possible commands

river solstice
#

for a server owner, they may be useful, for a developer, it's a pain in the ass

dense drift
#

=check @proud pebble

neat pierBOT
#
No Spigot Account Linked!

Seems they don't have an account linked?

dense drift
#

Pff

#

What happened lol?

forest jay
#

What would be the best way to find a block in a specific region? I want to find all the doors in a given region, and I feel that looping through everys ingle block is super inefficient

sterile hinge
#

without any information about the region, you won't find a better way

#

but if you know anything about the region, there might be better approaches

#

e.g. if you know that the doors are the highest blocks at their x/z positions, you can reduce the problem from 3d to 2d

forest jay
#

Yeah, I literally know nothing about the regions, so I guess I should just be as efficient as possible in my checks.

minor summit
#

well doors are 2 blocks tall so you can check every 2 blocks in the y axis lol

#

or did mojang add some kind of 1 block tall door?

sterile hinge
#

trapdoor 🤓

minor summit
#

okay how about

#

#door

forest jay
sterile hinge
#

yeah then doing what emily said makes sense

dense drift
#

#wooden_doors actually according to the vanilla wiki

minor summit
#

what about the iron door?

dense drift
#

Fuck iron door

minor summit
#

doors is a valid tag that encompasses wooden doors and the iron door

#

gaby you disappoint me

dense drift
#

Sorry 😢

forest jay
#

I made the mistake of printing out each block in the region, and now the server wont stop. its literally looping through like 1 million blocks and printing each one lol

#

I forgot to remove it from my earlier test

dense drift
#

But can you just pass #tag to WE via code?

minor summit
#

well not "just pass", but yes it can be done with ease

dense drift
signal grove
#

well

#

what is your use case actually

#

all doors? or player placed ones

proud pebble
#

very sadge

dense drift
#

Open a ticket

forest jay
signal grove
#

and then, what will happen to the doors after you find them

forest jay
#

I just want their location

proud pebble
#

i dont see any channels or what not to even create one

signal grove
#

if you absolutely need their location, gotta follow the other peoples solutions with WE i guess

#

but i meant what youre doing with them, just trying to avoid an XY problem

zenith forum
#

Hello, is this chat where questions about the plugin are asked?

minor summit
#

what plugin?

zenith forum
#

DeluxeMenus

minor summit
zenith forum
#

Ok, ty

minor summit
#

np

dusky wolf
#

Any idea why this happens with my plugin?

    at java.util.HashMap.hash(HashMap.java:338) ~[?:?]
    at java.util.HashMap.getNode(HashMap.java:568) ~[?:?]
    at java.util.HashMap.get(HashMap.java:556) ~[?:?]
    at org.bukkit.plugin.SimplePluginManager.subscribeToPermission(SimplePluginManager.java:863) ~[pufferfish-api-1.19.3-R0.1-SNAPSHOT.jar:?]
    at org.bukkit.permissions.PermissibleBase.calculateChildPermissions(PermissibleBase.java:203) ~[pufferfish-api-1.19.3-R0.1-SNAPSHOT.jar:?]
    at org.bukkit.permissions.PermissibleBase.calculateChildPermissions(PermissibleBase.java:206) ~[pufferfish-api-1.19.3-R0.1-SNAPSHOT.jar:?]
    at org.bukkit.permissions.PermissibleBase.calculateChildPermissions(PermissibleBase.java:206) ~[pufferfish-api-1.19.3-R0.1-SNAPSHOT.jar:?]
    at org.bukkit.permissions.PermissibleBase.calculateChildPermissions(PermissibleBase.java:206) ~[pufferfish-api-1.19.3-R0.1-SNAPSHOT.jar:?]```
#

I tried deleting every hashmap and bukkitschedulers and it was still happening, this issue started happening randomly

dusky wolf
sterile hinge
#

when does it happen?

dusky wolf
# sterile hinge when does it happen?

this stackoverflowerror only happens when starting the server, if you would remove the plugin, let the server start then load the plugin with plugman/serverutils it would load

sterile hinge
#

so during onEnable? Which of the logging messages there are printed?

dusky wolf
sterile hinge
#

can you share your logs?

dusky wolf
#

for sure

dense drift
#

Same permission as the parent

dusky wolf
#

oh wait

#

wtf

#

lmfao

#

the issue was that

#

thanks a lot

sterile hinge
#

good job spigot at validating such simple things lol

spiral prairie
#

Lmao

#

This is the stupidest thing i have ever seen

dusty frost
#

does command prompt even support colors?

hoary scarab
dusty frost
# hoary scarab yes

i uh, feel this is untrue, have you ever actually seen colors in command prompt? and also have you considered using a terminal emulator made within the last 30 years

hushed badge
#

it does

dusty frost
#

full unicode colors? or like basic bash colors

hoary scarab
#

Paper does it

#

Can't show that at the moment though

dusty frost
#

well, my point still stands, use WIndows Terminal or something lol

hoary scarab
#

Also if I add the ESC unicode as an echo in the bat file it works

icy shadow
#

show the code for color and translate

hoary scarab
#

However the code isn't the issue as everything is replaced properly. Unless I am using the wrong unicode which I have tried multiple.

icy shadow
#

yeah it's definitely just command prompt being bad

hoary scarab
#

So odd. Ill show with paper and spigot later.

icy shadow
#

works consistently across 4 different terminal emulators for me

hoary scarab
#

Even tried adding -Dfile.encoding=utf-8 to the bat

icy shadow
#

cant test with old command prompt since it's gone on windows 11 but it works fine on windows terminal

#

actually yeah i can

#

doesnt work on conhost.exe

#

it's just the old emulator being bad

hoary scarab
icy shadow
#

you can bypass that, mine's "not" either

hoary scarab
#

Yeah IDK how cpu's that are older are compatible but mine aren't (pc and laptop)

#

I'll show on paper and spigot here in a bit

dense drift
#

Only newer versions of paper made the colors to work on cmd iirc

hoary scarab
#

They still work though lol

pulsar ferry
#

Windows terminal is available on windows 10 too, you just need to get it in the store instead of it being the defaul

icy shadow
#

^

hoary scarab
#

Ok but how do spigot and paper color the console without that?

minor summit
#

They don't, log4j does

dusty frost
#

the two things it does: rce and colors in cmd.exe 😌

dense drift
#

if you want to make a better api than spigot, dont follow spigot kek

hoary scarab
#

I'm not just trying to get an idea of how they solved it

dense drift
#

you can solve it by using a scary, yet useful, external library octo_ghost

proud pebble
#

maybe its failing cus the terminal doesnt think its in ansi mode or whatever

hoary scarab
#

What do you mean?

#

Also keep in mind spigot and paper display colors

proud pebble
#

cus atleast during 1.8 it didnt support ansi so it wouldnt show colors in terminal

proud pebble
icy shadow
#

If I had to guess there’s some god awful hack builtin to spigot/log4j specifically for this purpose

#

seeing as the normal codes just don’t work

hoary scarab
icy shadow
#

ok?

proud pebble
#

i wouldve assumed the hack was built into spigot and not the libs

icy shadow
#

More likely yeah

hoary scarab
#

Only thing I found "color" wise was the image for ColoredConsoleSender above. And even if I match that I still don't get colors.

icy shadow
#

Spigot sure does love supporting ancient shit

proud pebble
minor summit
#

Oh man the StackExchange app crashes

#

What a great time to uninstall it

proud pebble
#

there has to be some way to enable colors in command prompt

icy shadow
#

there is indeed, as the thread says

proud pebble
#

yeah, its just finding it

#

finding the specific java one

icy shadow
proud pebble
#

i saw mentions of jansi

icy shadow
#

and has some old windows hacks

proud pebble
#

weird champ ngl

icy shadow
#

if only there were an alternative to conhost that didnt require any external libraries or hacks

#

...did you not read the past 7 minutes?

hoary scarab
#

ok i was basically correct, spigot uses jansi which has native bindings for windows
Didn't see that message no. Give me a sec

dusky harness
#

Does cmd prompt not support ansi?

#

I'm pretty sure it does

icy shadow
#

okay i am going to go nerd emoji here

dusky harness
#

Or I was using smth else

icy shadow
#

technically command prompt is the shell

#

what you probably mean is conhost.exe, i.e. the old terminal emulator

#

which has been superceeded by windows terminal

#

conhost does not natively support ansi colours, you can hack around it with some native fuckery

#

which jansi (i.e. spigot) does

#

windows terminal does natively support ansi colours (and is better in literally every way)

minor summit
#

superseded* 🤓

minor summit
#

yes it is your bad

dusky harness
minor summit
#

true

icy shadow
#

real

minor summit
#

RIP that server

dusky harness
#

nerdemily why r there so

#

2

#

Oh that's from dev den

minor summit
#

RIP that server too

icy shadow
#

why r there so 2

dusky harness
dusky harness
icy shadow
#

why r there so 2 typo

lyric gyro
#

14:08:33 [WARNING] Error enabling plugin PlaceholderAPI
java.lang.NoClassDefFoundError: org/bukkit/plugin/java/JavaPlugin
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at net.md_5.bungee.api.plugin.PluginClassloader.loadClass0(PluginClassloader.java:44)
at net.md_5.bungee.api.plugin.PluginClassloader.loadClass(PluginClassloader.java:37)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
at net.md_5.bungee.api.plugin.PluginManager.enablePlugin(PluginManager.java:329)
at net.md_5.bungee.api.plugin.PluginManager.loadPlugins(PluginManager.java:237)
at net.md_5.bungee.BungeeCord.start(BungeeCord.java:436)
at net.md_5.bungee.BungeeCordLauncher.main(BungeeCordLauncher.java:32)
at net.md_5.bungee.Bootstrap.main(Bootstrap.java:15)
Caused by: java.lang.ClassNotFoundException: org.bukkit.plugin.java.JavaPlugin
at net.md_5.bungee.api.plugin.PluginClassloader.loadClass0(PluginClassloader.java:63)
at net.md_5.bungee.api.plugin.PluginClassloader.loadClass(PluginClassloader.java:37)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)

dusky harness
#

Bc I am on mobile

icy shadow
dusky harness
icy shadow
#

too slow

dusky harness
#

I am on mobile

#

😖

icy shadow
#

so am i

dusky harness
#

Oh

#

Uh

icy shadow
#

sorry that was a lie

#

i was lying

#

dont worry

warm steppe
#

i know a fix for the color issue

dusky harness
minor summit
#

oh boy

icy shadow
#

do tell

dusky harness
#

Yea

minor summit
#

it's almost as if the whole thing hasn't been addressed 7 minutes ago

dusky harness
minor summit
#

Sorry, 8

icy shadow
#

twice, even

minor summit
#

Wanna make that three?

warm steppe
#

in onEnable() add this:

if (!PaperLib.isPaper()) {
    PaperLib.suggestPaper(this);
    Bukkit.getPluginManager().disablePlugin(this);
}
dense drift
#

lol

icy shadow
#

that uh

#

has nothing to do with the conversation but nice try i guess

minor summit
#

okay someone has been not reading chat for like a whole month ig

warm steppe
#

wouldn't it fix the issue?

icy shadow
#

do you know what the issue is?

warm steppe
#

colors not working in console on spigot?

dense drift
#

he knows half 🤣

hoary scarab
#

Not even half lol

icy shadow
hoary scarab
#

Yeap jansi worked. Now I gotta figure out how lol

icy shadow
#

a lot of JNI C code

#

which would take quite a while to copy & get working

hoary scarab
#

Actually looks like it just makes its own output streams and does what I am already doing with replacing the colors. (Over simplification)

#

And works without logj4

icy shadow
#

That is a dramatic oversimplication as that isn’t actually the part solving the problem

#

conhost does not support ansi codes no matter how you write or replace them

hoary scarab
#

Well I'm closer then I was about 6 hours ago xD

conhost does not support ansi codes no matter how you write or replace them
I know

icy shadow
#

Just to reiterate, windows terminal doesn’t need windows 11. You could’ve installed it by now and saved yourself 6 hours of effort

hoary scarab
pulsar ferry
minor summit
#

"without additional software" seems very vague

#

you could argue any text editor is additional software

#

and neither a modern terminal emulator nor a text editor is part of what makes a Minecraft server a Minecraft server

#

ANSI escape codes not working is not a problem with your software, it's a problem with Windows conhost

icy shadow
#

yeah the native jansi hack is technically additional software

hoary scarab
#
private void print(String s) {
    String edit = get().color(get().translate(s));
        
    if(isWindows) {
        try {
            new ProcessBuilder("cmd", "/c", "echo " + edit).inheritIO().start().waitFor();
        } catch (InterruptedException | IOException e) {
           e.printStackTrace();
        }
    }else {
        System.out.println(edit);
    }
}
    
private boolean isWindows = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win");
#

Done

#

lol

dusky harness
#

did you test with windows terminal

#

also hows that solution work?

#

no idea what that does

hoary scarab
#

Basically uses commands in the console for supported ansi

minor summit
#

how doesn't that break the "no additional software" philosophy when you are explicitly requesting for additional software lol

hoary scarab
#

Its using the echo command which is already in the software I am using 😉

minor summit
#

no the jdk doesn't bundle the echo command

#

nor the cmd command

hoary scarab
#

Lets put it this way. I didn't have to download anything or add any api's, libs etc...

minor summit
#

and how is this crucial for a minecraft server to function

dense drift
#

more ram might speed up the process

hoary scarab
#

Its preference

minor summit
#

lol alright

#

but it is still external software

#

foreign to your application

kind granite
#

have you considered the overhead of spawning a process like that for every single line you output

hoary scarab
#

Also jansi just enables virtual processing so instead of adding the JDK's for windows kernal32 its easier to just process a command.

minor summit
#

minor inconveniences

pulsar ferry
#

I'm just very confused why you're so against using libraries or apis that'll make your life much much easier

icy shadow
#

it's not looking good (although admittedly im microbenchmarking)

hoary scarab
minor summit
#

exactly

icy shadow
#

indeed

#

there is no solution that doesnt require external software, so you may as well just use a modern terminal

hoary scarab
#

I'm not writing java from scratch. I'm just not using additional libs/api's

kind granite
#

why

hoary scarab
#

Cause I want to lol

#

And so far I haven't seen anyone else do it.

icy shadow
#

that is a separate process, not written in java, that has nothing to do with your app

dense drift
hoary scarab
icy shadow
#

no you could not

kind granite
#

well

#

yeah

dense drift
minor summit
#

not java but the jdk

pulsar ferry
# hoary scarab And so far I haven't seen anyone else do it.

Probably because it's a worse way to go about it that requires much much more unecessary work
Most that try already give up before doing even a bit of what is needed while using things that make it easier so I can expect this to go very far

hoary scarab
icy shadow
#

because by using the java language you've already entered into a contract that says all these things exist

#

it's external, but it's not additional external software

dense drift
#

where is the hidden camera? kek

dusky harness
hoary scarab
#

Probably because it's a worse way to go about it that requires much much more unecessary work
All I have is time lol.

pulsar ferry
#

That could be spent on more important things ;p

dense drift
#

like re-inventing the wheel wdym matt

minor summit
#

like actually implementing minecraft lol

dusky harness
#

it's hard enough implementing minecraft with the help of libraries

#

🙃

pulsar ferry
#

Just pull a bardy, do just a bit more and then port luckperms to it omega_lul

icy shadow
#

by my not-very-accurate microbenchmarks, launching a separate process is 900x more expensive than just a System.out.println call. that will add up and become significant

hoary scarab
#

If I say I have all the time I need... That would mean there is nothing more important.

mental cypress
#

Can I get a ChatGPT analysis to back that up Brister?

icy shadow
#

analysis on what? the numbers or the method?

mental cypress
#

The numbers

icy shadow
#

uh well

#

it's just division lmao

#

in fact my benchmark is probably actually being generous to the processbuilder method, since i cant figure out how to launch a whole separate shell with processbuilder lmao

dense drift
#

I would write an assembly implementation if I had THAT much time, no joke

floral beacon
#

Hello,
i am using DynamicPremium plugin which works similarly like FastLogin (used mainly on online-mode: false servers to enforce usage of premium account for specific selection of users) and allows auto-login if used on spigot (subserver) side

I have forked this project but didn't make any big changes other than some hardcoded translating things but i've prepared to make changes in order to fix the issue i am presenting here and seeking for someone to figure out what is wrong because i really don't know what is happening wrong here.

These are the logs that happens when player joins the server

these are the target java classes that are mentioned in the logs

What happens is that every now and then (from what i figured out, every time my premium account session expires / is not anymore verified by mojang servers) and some time passes after i try to join with my premium account again - i get these errors on both bungee and spigot side of the plugins (respectively, i posted logs for both above). However I can't understand why it happens, every other plugin that is connected to my mysql database server works very fine and i have like 5+ of them on multiple different mc servers.

Any ideas? PS. i contacted the owner multiple times, no response (he's obviously very absent)

icy shadow
mental cypress
#

Dear lord

dense drift
icy shadow
#

i am sure this is a good idea

minor summit
#

Also I believe printing to conhost is actually slower than Windows Terminal, I'm fairly sure

icy shadow
#

lets find out!

#

just for science

minor summit
#

My favourite thing to do is to cat /dev/urandom

dense drift
#

can we write logs on a piece of paper?

icy shadow
#

that might be faster

#

and it supports colours!

dense drift
#

as long you have ink though

mental cypress
#

Yeah but then I have to bust this bad boy out if I want HEX colors

dense drift
#

you will need more if you want to support all 16 million of them

icy shadow
#

what about paint?

#

that supports easy colour blending for the full range

dense drift
#

and can replicate the mc font easily

icy shadow
#

true

#

it's perfect

mental cypress
#

I discovered KDocs + Dokka today and I'm loving that it uses the Jetbrains font. Feels kind of like looking at your IDE.

icy shadow
#

i love jetbrains mono

mental cypress
#

Yeah I added that in as a font to MCBanners iirc

icy shadow
# icy shadow lets find out!

okay the windows results are a little more forgiving but still very not good:
windows terminal (powershell) = 66481ms (process) or 327.7ms (sout) for a difference of 202x
windows terminal (command prompt) = 66658ms (process) or 325ms (sout) for a difference of 205x
conhost = 75071.9ms (process) or 301.71 ms (sout) for a difference of 248x

take the results with a medium-large pinch of salt, they're not proper benchmarks. but there is clearly a big performance cost for PB and conhost seems to be slowest

#

and that's not even looking at the memory costs of spawning a new shell every time you want to print something

minor summit
#

who cares about memory costs when you have swap!

#

infinite memory

icy shadow
icy shadow
#

and just because i love you all, i even tested on my vps so we get a full trilogy of processbuilder being bad

#

oh my

#

ok

#

on linux it's 405x slower 💀 however that may be due to the network overhead of having to print stuff over ssh

#

pinch of salt

#

the point is that this is not a good idea

hoary scarab
#

Surprised no one mentioned that it also creates files xD

icy shadow
#

Does it?

hoary scarab
#

SERVER and CLIENT yeah

#

atleast it keeps making them for me xD