NFAQ - CryptoMorin/KingdomsX GitHub Wiki

Not Frequently Asked Questions

But we're here to answer them anyways.

Table of Contents


Creating custom turrets

Kingdoms comes with several powerful turrets by default, but also allows server owners to create their own custom ones. All the turret configuration files are located in the Turrets folder.

The basic workflow for creating a new turret is as follows:

  1. Begin by creating a new YML file for your turret in the Turrets folder.
  2. Copy the configuration of one of the existing turrets (from arrow.yml for example) and paste it into your new one.
  3. Modify the settings to make your new turret unique.
  4. Make your turret available for purchase in the Nexus by adding it to the GUI in guis -> <lang> -> structures -> nexus -> turrets.yml. Simply copy one of the purchase buttons for other turrets and use it for your new one. Make sure that the button is named the same as in step 1 (without the .yml part; see example for arrow turret), and don't forget to change the posx and posy so it doesn't overlap existing items.
  5. In guis -> <lang> -> turrets create a new YML file that is named exactly the same as in step 1. This will be the GUI shown when you right-click the turret after it's been placed, containing upgrade, ammo and buttons for other options.
  6. Copy one of the guis of existing turret (eg. arrow.yml) and paste it into your new file. Configure it to your liking.

Note

Please refer to this section for a more detailed explanation and an example custom turret that you can use for your server.

Making custom misc upgrades

We're going to be making a custom misc upgrade that adds permission for players. Thankfully LuckPerms Contextual Permissions make this easier.

  1. In misc-upgrades.yml we're going to add a new entry.
custom-misc-upgrade: # The name here will be important later for permissions and GUIs
  enabled: true
  can-be-disabled: true
  max-level: 3
  1. Make a new permission group using /lp creategroup kingdoms. This is where all kingdom related permissions will be defined. It's mostly for organization purposes.

  2. We need to install ExtraContexts official LuckPerms addon to work with PlaceholderAPI-oriented contexts.

  3. Enable placeholder API support in ExtraContexts config.yml and add the a new placeholder for the misc upgrade:

placeholderapi: true
placeholderapi-placeholders:
  allowflight: "%player_allow_flight%"
  customMiscUpgrade: "%kingdoms_kingdom_upgrade:level type=misc, of=CUSTOM_MISC_UPGRADE%"

Here we used a complicated functional placeholder. The of option is determined by the config entry name. We used custom-misc-upgrade. A rule of thumb is that whatever name you used, make all the characters uppercase and replace - with _.

  1. Add contextual permissions:
  • /lp group kingdoms permission set kingdoms.misc.custom.1 true customMiscUpgrade=1
  • /lp group kingdoms permission set kingdoms.misc.custom.2 true customMiscUpgrade=2
  • /lp group kingdoms permission set kingdoms.misc.custom.3 true customMiscUpgrade=3

image

Here we chose kingdoms.misc.custom.x, but really, it could be any permission! customMiscUpgrade is the context which relies on a single integer.
We only added 3 of them, because the max level is 3. If you want more levels, go back to step 1 and change the max-level option.

  1. Make the default group inherit our newly created group: /lp group default parent add kingdoms
    This will allow all permissions to automatically use this group no matter what. Now, you might be asking, doesn't this give them the permissions right away whether they have the upgrade or not, or even in a kingdom at all? No, it doesn't because we used contextual permissions which is basically a way of saying "you only have this permission if a certain condition is met" and those conditions being our contexts, i.e. customMiscUpgrade=x

If your higher groups (donator ranks, mod, admin, etc) don't inherit the default group for some reasons, you also have to add them to these groups too.

image

  1. Finally we can verify that it works: /lp user <player> permission check kingdoms.misc.custom.1

We can also check what's the current context of the player using /lp user <player> info

Note that contextual permissions are not that perfect. If you for whatever reason needed to check these permission for a player that's offline, it won't work correctly due to performance issues from LuckPerms side.

  1. Add it to the GUI so players can actually upgrade it. Just adding it to the misc-upgrade.yml is not enough, we need to manually open a slot for it inside misc-upgrades.yml GUI

The GUI's layout is designed to look nice with the default amount of upgrades. So if you want to add it, you should reposition all options.

options:
 custom-misc-upgrade: # We just reused the same name as it is
   name: "&2My Custom Misc Upgrade"
   material: DIAMOND_BLOCK
   lore: |
     &7Gives you cool permissions
   posx: x
   posy: y

Also to translate the name shown in chat for %upgrade% placeholder, you can add it to your language file upgrades -> misc -> custom-misc-upgrade -> name

9. Bonus Step: Upgrade Trees & Commands

You can make another upgrade to be only enabled if a certain condition is met, this works for all upgrades as well. Let's say we only want someone to upgrade this permission if they upgraded max members to the maximum level and they have at least 10 members.

custom-misc-upgrade:
  enabled: true
  can-be-disabled: true
  max-level: 3
  condition:
    "{kingdoms_kingdom_upgrade:level type=misc, of=MAX_MEMBERS} < 10": "miscupgrades.required.max-members"
    "kingdoms_members < 10": "miscupgrades.required.members"

Here the keys are conditions and the values are paths to the entry to the error message to send to that player and prevent them from upgrading it if that condition is met. These entries are not defined by default and it can be any entry. You have to add them to your language files like en.yml

Database Issues

Outdated MySQL

java.lang.RuntimeException: java.sql.BatchUpdateException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'JSON NULL,`claims` JSON NULL,`protectedBlocks` JSON NULL,`mutedChannels` JSON NU' at line 1
Caused by: java.sql.BatchUpdateException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'JSON NULL,`claims` JSON NULL,`protectedBlocks` JSON NULL,`mutedChannels` JSON NU' at line 1
Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'JSON NULL,`claims` JSON NULL,`protectedBlocks` JSON NULL,`mutedChannels` JSON NU' at line 1
        at org.kingdoms.libs.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[KingdomsX-1.16.19.jar:?]
        at org.kingdoms.libs.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[KingdomsX-1.16.19.jar:?]
        at org.kingdoms.libs.mysql.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:763) ~[KingdomsX-1.16.19.jar:?]
        at org.kingdoms.libs.mysql.cj.jdbc.StatementImpl.execute(StatementImpl.java:780) ~[KingdomsX-1.16.19.jar:?]
        at org.kingdoms.libs.mysql.cj.jdbc.StatementImpl.executeBatchUsingMultiQueries(StatementImpl.java:1019) ~[KingdomsX-1.16.19.jar:?]
        at org.kingdoms.libs.mysql.cj.jdbc.StatementImpl.executeBatchInternal(StatementImpl.java:839) ~[KingdomsX-1.16.19.jar:?]
        at org.kingdoms.libs.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:795) ~[KingdomsX-1.16.19.jar:?]        at org.kingdoms.libs.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:127) ~[KingdomsX-1.16.19.jar:?]        at org.kingdoms.libs.hikari.pool.HikariProxyStatement.executeBatch(HikariProxyStatement.java) ~[KingdomsX-1.16.19.jar:?]
        at org.kingdoms.data.database.sql.SQLDatabase.<init>(SQLDatabase.java:60) ~[KingdomsX-1.16.19.jar:?]
        ... 16 more

This simply means that your MySQL server is outdated and needs to be updated. If your host provides a panel, you can update your MySQL from there, if not, you can manually download and install from the official MySQL download page.

SSL

Caused by: org.kingdoms.libs.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors

// or

Caused by: java.sql.SQLNonTransientConnectionException: SSL Connection required, but not provided by server.
Caused by: org.kingdoms.libs.mysql.cj.exceptions.UnableToConnectException: SSL Connection required, but not provided by server.

You simply need to set ssl option to false and restart the server.

Public Key Retrieval is not allowed

Caused by: java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
Caused by: org.kingdoms.libs.mysql.cj.exceptions.UnableToConnectException: Public Key Retrieval is not allowed

You simply need to stop your server first, then set config.yml -> allow-public-key-retrieval to true and restart.

maxLifeTime vs wait_timeout

[org.kingdoms.libs.hikari.pool.PoolBase] kingdoms-hikari - Failed to validate connection org.kingdoms.libs.mysql.cj.jdbc.ConnectionImpl@... (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.

This can occur because of several reasons:

  • Your maximum-lifetime option in config.yml is higher than your wait_timout option in MySQL/MariaDB. The solution would be to simply either decrease maximum-lifetime or increase wait_timeout.
  • There's a firewall between your Minecraft server and the MySQL server that terminates MySQL connections itself. Obviously the fix would be to check your firewall settings.
  • Can be caused by SQL Proxies or HAProxy. You should check their timeouts and max connection settings as well.
  • There's a chance that this might happen because you're running your server in a VM.
  • This can also happen when a low net.core.somaxconn kernal parameter is set for your system.

Host is blocked because of many connection errors

Caused by: java.sql.SQLException: CLI-specific condition,  message from server: "Host '...' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'"

This means that you had an error in your previous restarts that you didn't pay attention to, now your database has locked down any connection until you fix the issue. What you need to do is to go back in your logs and see when this error started happening. You'll likely find another error message that is slightly different than this message. If you couldn't find the solution to the first error in this FAQ, you can report the logs to the developers.

Note

After you fixed the error, you need to run mysqladmin flush-hosts like the error says. Otherwise this error will continue to happen. If you don't have direct SSH access to the database server, you can manually run the FLUSH HOSTS SQL statement instead. Make sure all of this is done when your server is not running.

Tip

If you're unable to find the first error, you can also flush hosts which lets you see the actual error the next time you restart. However, in rare cases the error might be hidden and require you to directly check your database logs for more information (for example, using the SET GLOBAL log_warnings = 2 SQL statement.)

Number of interrupted connect requests allowed is determined by the value of the max_connect_errors system variable. After max_connect_errors number of failed requests, mysqld assumes that something is wrong (for example, that someone is trying to break in), and blocks the host from further connections.

EntityRemoveEvent Warning

[Server thread/WARN]: [KingdomsX] "Kingdoms v..." has registered a listener for org.bukkit.event.entity.EntityRemoveEvent on method "private static void org.kingdoms.utils.hash.EntityHashHandler$a.a(org.bukkit.event.entity.EntityRemoveEvent)", but the event is Deprecated. "Server performance will be affected"; please notify the authors [Crypto Morin].

This is a misleading message added by Paper in one of their recent v1.21 updates. This error claims that this affects server performance which is wrong and it's simply a generic message for server owners to bother developers for no reason. This however was fixed in newer Paper versions. So you simply have to update your Paper to the latest v1.21.4 build in order to fix this issue or you could simply ignore it as it doesn't really affect anything.

Possible Malware Detections

In this section I'll answer some questions about the plugin being detected as possible malware due to the heavy "hacky" code it uses to bypass some limitations. Keep in mind that Minecraft developers were forced to resort to hacky solutions from the start due to how Minecraft's code works.

Note

As of Kingdoms v1.17.13-BETA, the plugin will automatically verify itself using an internal hash without requiring an internet connection. This is only useful when a virus is designed to inject files/code into other plugins. However, it's obviously not useful against MITM attacks.

Note

The plugin is obfuscated merely because of Spigot's file size limit. The standard file size limit for direct uploads to Spigot is 4MB and we had to have several discussions with Spigot's team to increase this file size limit now that our plugin is around 6MB. However, this obfuscation is designed to minimize the size as much as possible, not to make the code harder to read, so most of the plugins code is still readable after being de-obfuscated, except some Kotlin classes that use advanced syntax and are pretty unreadable even without obfuscation.

Last Update Info:

VirusTotal

If you run the plugin through VirusTotal, you'll see that the plugin comes back with zero threats.

Image showing VirusTotal's report summary of Kingdoms

PluginScan & ByteScan

If you use services that are designed with Minecraft plugins in mind, such as PluginScan and ByteScan Discord you'll see several threats which are reasonable. The threats shown here are only from PluginScan, however ByteScan will basically show the same threats.

Note

This section requires you to have advanced knowledge of Minecraft plugins and Java in general. If you don't, you will not understand any of the things mentioned here and you'll need to discuss this with your server developers. If you have any questions, I'll try to answer them.

Image showing PluginScan's report of Kingdoms

org.kingdoms.utils.internal.ProxyBytecodeManipulator

A class that contains experimental code, some code in that class are never used, but they're all quite "dangerous" in the fact that it may simply break things or its functionality might break in future spigot updates. Right now the only thing it does is injecting custom kingdoms command and loading/unloading addons.

org.kingdoms.asm.SafeClassDefiner

This is entirely an experimental class as well, it's not used anywhere in the plugin. It's basically kept for future updates when Forge and Fabric support is added. It basically makes it possible to register custom events to all platforms other than Bukkit.

Class Loaders

in org.kingdoms.dependencies.classpath.IsolatedClassLoader
in org.kingdoms.dependencies.classpath.JarInJarClassLoader
in org.kingdoms.dependencies.classpath.JarInJarClassPathAppender
in org.kingdoms.dependencies.classpath.ReflectionClassPathAppender

in org.kingdoms.libs.asm.ClassReader
in org.kingdoms.libs.asm.Constants

These all do one thing. They basically download and load external libraries. This is marked as dangerous because it really is as it basically fiddles with low-level Java mechanics (basically similar to machine code for computers) due to how Minecraft plugins work in general. The library marked here is ASM it's pretty much industry-standard.

  • Why does the plugin download libraries in the first place? Because if the mentioned file size limit libraries cannot be shaded and the fact that the plugin shouldn't be shipped with unnecessary libraries if your server doesn't even use them. For example, if you use H2 database, there is no reason to load MySQL drivers as well.
  • What libraries does the plugin download? Mostly utility classes which most of them are open sourced. Such as XSeries, database drivers and Java utilities that help with performance.
  • Where are the libraries downloaded from? Maven. While any malware can easily be uploaded to Maven, the plugin only uses the known libraries which are mostly open source. You can check these downloaded libraries in the Kingdoms/libs folder.

If you run the same scan using PluginScan but for LuckPerms, you'll receive a similar detection. Kingdoms pretty much uses the same thing for loading libraries as LuckPerms. The reason why it isn't being fully detected is because LuckPerms jar itself is nested. It's basically a .jar in another .jar file and anti-viruses cant property detect these:

Image showing PluginScan's report of LuckPerms with 2 threats Image showing LuckPerms JAR archive content

Others

Image showing ByteScan's report

  • [MODERATE] Possible binary embedded in class file: This is simply because the class is too complex and its size is unusually big.
  • [MODERATE] Plugin can load new plugins in runtime (CommandUpdates): Yes, it can! That's how Kingdoms handles addons with /k admin addons
  • [MODERATE] Plugin can set player's op status (ConfigCommand): Yes, it can! That's used when you define a OP:command... option inside a config and it runs the command as the player as if they were OP and had all permissions.
  • [LOW] Plugin can hide malicious references by using reflection: This simply goes back to Minecraft limitations. A lot of developers use reflection to bypass limitations and shortcomings of Spigot's API to access great features.
  • [LOW] Multiple listeners found: I'm not sure how this is even a threat, most plugins have listeners, it's a pretty documented Bukkit API.
  • [LOW] Possible class injection (or just a library): They're just utility classes for the plugin.
⚠️ **GitHub.com Fallback** ⚠️