Compare commits

...

199 Commits

Author SHA1 Message Date
Christian Koop e3153653ff
GitHub Actions: Updates projectKey and organization for SonarCloud
I've editted the organisation on SonarCloud and the organisation key changed.
2023-05-07 20:02:29 +02:00
Christian Koop 3dc48dabd3
README.md: Updates badges 2023-05-07 19:01:43 +02:00
Christian Koop fa355cbdcc
GitHub Actions: Don't trigger SonarCloud for PRs but workflow_dispatch
They turns green if the PR comes from an outside collaborator because all steps
are skipped if the SONAR_TOKEN is not set.

I'd rather not run static analysis on PRs overall than having it turn out green.
2023-05-07 19:00:12 +02:00
Christian Koop f00f157bfb
GitHub Actions: Updates actions/checkout from v2 to v3
Somehow Dependabot errors out when trying to check for updates
2023-05-07 18:40:27 +02:00
Christian Koop 55d4c7036b
GitHub Actions: Remove listening for pushes to development-v3 branch
The branch does not longer exist and has been merged
2023-05-07 18:25:34 +02:00
Christian Koop a78c2a832e
GitHub Actions: Only deploy to maven repo on push event and not PRs 2023-05-07 18:25:00 +02:00
Christian Koop 880d9d36e0
Merge branch 'development' 2023-05-07 15:19:08 +02:00
Christian Koop 9c4923cd42
Release v2.6.22
I'm creating this release to push the GitHub Actions and Dependabot changes to the main branch.
Dependabot should find at least 2 outdated actions dependencies and create a PR for them.


Please check #47 for a list of *most* changes.
2023-05-07 15:19:04 +02:00
Christian Koop edb62751ba
GitHub Actions: Set increment_version to patch outside of tags
When we release v.2.20.1 and add a commit, v2.20.1-SNAPSHOT is published,
which is not the correct version.
patch-level isn't right either always, but I think that's a good compromise for now.
2023-05-07 14:58:43 +02:00
Christian Koop 2c1f8bbdf8
Merge pull request #47 from craftaro/development-v3-without-breaking-changes
Merges the original development-v3 branch and reverts commits that introduce breaking changes
2023-05-06 23:32:10 +02:00
Christian Koop 3e233cf021
Revert the project's version back to '2.6.21' 2023-05-06 22:54:50 +02:00
Christian Koop 5e21ac9424
Revert deletion of NmsManager, deprecate it and have it use the new one 2023-05-06 22:44:38 +02:00
Christian Koop 17780fffdc
Introduce constants GitHubProjectURL+ProjectName in SongodaCoreConstants 2023-05-06 22:44:38 +02:00
Christian Koop 3722ebb46a
Fix a couple compile errors after a lot of reverts and merges 2023-05-06 22:44:38 +02:00
Christian Koop b6a4198a60
Revert "Version v3.0.0-SNAPSHOT"
This reverts commit a06d27ab90.
2023-05-06 22:44:38 +02:00
Christian Koop 5e093558a4
Deprecates BlockUtils#updateAdjacentComparators(Location) 2023-05-06 22:44:38 +02:00
Christian Koop 50d5784da8
Partially reverts "Replace #updateAdjacentComparators implementation(+ move to NMS modules)"
This partially reverts commit 3d20f439e1.
2023-05-06 22:44:38 +02:00
Christian Koop dc82a6ba5c
Deprecates BlockUtils#setBlockFast methods 2023-05-06 22:44:38 +02:00
Christian Koop 1240c75bfa
Partially reverts "Replace #setBlockFast implementation and move into NMS modules"
This partially reverts commit 43148032a2.
2023-05-06 22:44:38 +02:00
Christian Koop ad8f8517a7
Deprecates SWorldBorder class
Related to:
* 71502be7d0a8978ede443b43c207c932f550730d
* 9d7026ec27
2023-05-06 22:44:38 +02:00
Christian Koop 426e786b49
Partially reverts "Replace SWorldBorder implementation and move it into NMS modules"
This partially reverts commit 9d7026ec27.
2023-05-06 22:44:38 +02:00
Christian Koop 0906cbf9c8
Deprecates `WorldCore#getSpawner(CreatureSpawner)`
It is a hussle to implement this method in every NMS version and doesn't provide much value.


Related to:
* e7bb4bf7634cfb27199fa88e047d138a896a229e
* 1cd96b10c5
2023-05-06 22:44:38 +02:00
Christian Koop 7c09845789
Revert "Remove overloading `WorldCore#getSpawner(CreatureSpawner)`"
This reverts commit 1cd96b10c5.
2023-05-06 22:44:38 +02:00
Christian Koop c725ea69d6
Revert all the SongodaYamlConfig related commits
Revert "Ensures usage of UTF-8 in SongodaYamlConfig"

This reverts commit 339a4d6f6c.

Revert "Improve test coverage + stability of configuration.yaml/songoda classes"

This reverts commit ef6c37b80c.

Revert "Adds ConfigEntry#withDefaultValue for easier chaining"

This reverts commit 88e28689f7.

Revert "Code cleanup (rename e->ex in catch; better type for #withUpgradeStep)"

This reverts commit 7eff3c86ec.

Revert "Rename constant into upper case to match code conventions"

This reverts commit 4d194ed92b.

Revert "Fix typo in JavaDoc"

This reverts commit 0b2a253014.

Revert "Makes SongodaYamlConfig#cannotCreateBackupCopyExceptionPrefix static"

This reverts commit 8e91cc18eb.

Revert "Make unit tests in LocaleFileManagerTest deterministic"

This reverts commit 67a69e34e8.

Revert "Add unit test for SongodaYamlConfig persisting comments on key-upgrades"

This reverts commit d710b2d2d5.

Revert "Improve temporary file deletion in YamlConfig and FileManager tests"

This reverts commit 02330b5ca7.

Revert "Adds hyphen before timestamp in file name, when creating backup YamlCfg"

This reverts commit f8b3942de2.

Revert "Fix YamlConfiguration not dumping comments"

This reverts commit e7da328dc6.

Revert "Provisional first implementation of the new localization system"

This reverts commit b168ad0738.

Revert "Fix error handling of SongodaYamlConfig#load(Reader)"

This reverts commit 163e4d9eaf.

Partially reverts "Adds some deprecation notices to configuration.editor classes"

This partially reverts commit eea951ecc6.

Revert "Redo ConfigEntry abstraction"

This reverts commit 20b44327e0.

Revert "Migrate CustomizableGui from old Config to SongodaYamlConfig"

This reverts commit d5ddde3e08.

Revert "Adds SongodaYamlConfig#getAsEntry(String) for convenience"

This reverts commit 20b7a353b8.

Revert "Add contract to `ConfigEntry#getString(String)` for non-null-argument"

This reverts commit 78b6039d39.

Revert "Adds getter to ConfigEntry for List<String>"

This reverts commit 3a09c19dbb.

Revert "Remove usage of Locale classes"

This reverts commit da3c89450e.

Revert "Mark overwritten and empty config methods in SongodaPlugin as deprecated"

This reverts commit 73685b62dd.

Revert "Adjust log levels in SongodaYamlConfig"

This reverts commit 7ef00bb8f9.

Revert "Fix SongodaYamlConfig not creating parent directory when saving"

This reverts commit b0f006aed0.

Revert "Fix SongodaYamlConfigTest leaving created backup files in tmp dir"

This reverts commit c9a48387de.

Revert "Remove Config related methods in SongodaPlugin"

This reverts commit fce5c5c6a1.

Revert "Introduce new SongodaYamlConfig and ConfigEntry classes"

This reverts commit eb10b3f70a.

Revert "Fix YamlConfiguration dumping null values and empty tree nodes"

This reverts commit 02ab8d4bb2.

Revert "Fix `YamlConfiruration#getKeys("")` not returning root node keys"

This reverts commit 885cc9a87e.

Revert "Fix exception on loading empty file in YamlConfiguration"

This reverts commit 2683bc12c0.

Revert "Make YamlConfiguration insertion-sorted"

This reverts commit 2262652577.

Revert "Rename `IConfiguration#getOrDefault` to `#getOr`"

This reverts commit f6e207cdda.

Revert "Adds Enum support to YamlConfiguration class (#41)"

This reverts commit 41bd5c633a.

Revert "Removes the default implementations for #save(File) and #load(File)"

This reverts commit 8f15df3601.

Revert "Replace Songoda's YAML Configuration wrapper with an own implementation"

This reverts commit 6d6fa7210a.
2023-05-06 22:44:38 +02:00
Christian Koop 748f10b77b
Merge branch 'development' into development-v3 2023-05-06 20:17:35 +02:00
Christian Koop 96097cb1ee
Merge branch 'development' 2023-04-29 12:37:50 +02:00
Christian Koop 0a0848c857
Release v2.6.21 2023-04-29 12:37:40 +02:00
Christian Koop 06761c001c
Fix plugin cmd list displayed in Action Bar instead of the chat 1.19.3+
The boolean flag determines 'whether the message is an actionbar or chat message'.
We want to have it set to `false` here.

Reference:
https://wiki.vg/index.php?title=Protocol&oldid=18120#System_Chat_Message
2023-04-29 11:56:04 +02:00
Christian Koop 24fc39ab16
Merge branch 'development' 2023-04-22 16:21:44 +02:00
Christian Koop 7a7d2e8b97
Release v2.6.20 2023-04-22 16:13:07 +02:00
Christian Koop 8d95084137
Adds missing Spawn Eggs to CompatibleMaterial, added in Minecraft 1.19.3
fixes #46
2023-04-22 16:13:07 +02:00
Christian Koop 9361fad0bf
Deprecate BlockUtils and BlockUtilsModern classes 2023-04-22 15:18:33 +02:00
Christian Koop eb76ba47ee
Deprecate the ClassMapping and MethodMapping classes
They are a huge pain to maintain... I should have put a stronger word against this when it got added...
2023-04-19 21:59:13 +02:00
Christian Koop e21db58a67
Reimplement BlockUtils#updateAdjacentComparators in WorldCore
The implementation broke in 1.19.4 mid-version.
Fixes `java.lang.NoSuchMethodException: org.bukkit.craftbukkit.v1_19_R3.CraftChunk.getHandle()`


Related commit: a3e73be1aa
2023-04-19 21:59:13 +02:00
Christian Koop 3c501036a4
Merge branch 'development' 2023-04-13 11:51:18 +02:00
Christian Koop 57f9f1f911
Fix coreVersion in SongodaCore class not being the correct release 2023-04-13 11:51:14 +02:00
Christian Koop 171e4884b0
Merge branch 'development' 2023-04-13 11:49:07 +02:00
Christian Koop 177ecb36e5
Release v2.6.19 2023-04-13 11:48:55 +02:00
Christian Koop 37a9ee8868
Adds missing commands to list when console is running songoda command 2023-04-13 11:35:19 +02:00
Christian Koop c34c8faa9c
Fix wrong permission configured for SongodaCoreUUIDCommand 2023-04-13 11:23:05 +02:00
Christian Koop b9293079e0
Fix broken Wiki-URL in CustomizableGui
The Wiki has moved/changed and is not redirecting properly sadly
2023-04-13 11:22:43 +02:00
Christian Koop 2730b91598
Have songoda-Command have 'craftaro' as alias and change wording to that
Not having the actuall command change allows of other plugins *finding* that command
in that way means not introducing a breaking change by accident ^^

+ It's very hacky the way I did it but tbh... Core v3 is somewhat around the corner anyways
2023-04-13 11:22:04 +02:00
Christian Koop 7c4e967dd8
Changes *some* Songoda wording to Craftaro
I don't want to introduce too much confusion or breaking changes
2023-04-13 11:18:12 +02:00
Christian Koop a3e73be1aa
Fixes a Spigot 1.19.4 NMS method singature changing
EpicAnchor is affected by that
2023-04-13 10:58:04 +02:00
ceze88 1455cf2d1c Fix enchant book loot 2023-04-11 19:23:05 +02:00
ceze88 3dd3a31f25 Add coordinate placeholders to loot commands 2023-04-07 20:46:14 +02:00
Christian Koop 824f674dcd
Change order of IP and UUID in 'license not found' message to match GUI
The marketplace first asks for the UUID - I changed the order in the message to match that order.
2023-04-06 10:06:58 +02:00
Christian Koop e33848adc5
Release v2.6.19-DEV 2023-03-29 21:16:28 +02:00
Christian Koop 32c2c74841
Fixes AnvilView/-GUI in v1_19_R3 2023-03-29 19:58:41 +02:00
Christian Koop 65f606ee83
Refactor `/songoda diag` command and change output formatting a bit
This should make reading the version information displayed easier.
No more confusing the plugin version vs. the core version.

Additionally fixed `Mb` to `MiB`.
2023-03-29 19:22:09 +02:00
Christian Koop 140c59ffa2
Merge branch 'development' into development-v3 2023-03-29 18:49:25 +02:00
Christian Koop 07374fdbfd
Configures the new v1_19_R3 NMS module in the NmsManager class 2023-03-29 18:22:13 +02:00
Christian Koop fafcf28e0b
Updates dependency item-nbt-api to v2.11.2 for Spigot 1.19.4 support
From the changelog:
>Add 1.19.4 as officially supported (2.11.1 will work fine on 1.19.4, but show a warning that it doesn't know about this version)
2023-03-29 18:21:41 +02:00
Christian Koop 6d84d84753
Switch LICENSE from GPLv3 to CC BY-NC-ND 4.0
Co-authored-by: Eli Rickard <38917063+EliRickard@users.noreply.github.com>
2023-03-29 18:06:35 +02:00
Christian Koop ecf472c6c7
Implement missing Methods in NMS v1_19_R3 after merge (+ code cleanup)
Related commit 6d8c3beeb3
2023-03-16 19:08:36 +01:00
Christian Koop 6d8c3beeb3
Merge branch 'development' into development-v3 2023-03-16 19:07:54 +01:00
Christian Koop 52f6c42266
Adds NMS Module v1_19_R3 for Spigot 1.19.4 compatibility 2023-03-16 09:46:40 +01:00
Christian Koop a79677d261
Updates Lands-ProtectionHook to use v6 of the API
The API changed and we are 2 major versions behind
This drops support for outdated version of *Lands* and re-adds support for the latest version.
2023-03-09 15:53:21 +01:00
Christian Koop 5199043a4b
Minor code refractoring on SongodaAuth
Just trying to make it a bit more readable and easier to understand at a glance.
2023-03-04 13:08:16 +01:00
Christian Koop 6145021ecb
Remove unused imports in SongodaAuth and apply code formatting 2023-03-04 12:47:53 +01:00
Christian Koop d9586cfe86
Slightly changes wording of 'missing-license' message
+ small refactoring – Putting the *expesive* method calls outside the string into variables
to easier see them, when trying to understand the code and the need
for its own thread for just printing some messages to  the console.
2023-03-04 12:38:33 +01:00
Christian Koop ca13e8b26e
Prints 'missing-license' message in the console as one long message
This prevents fragmentation of the idividual lines. `#getIP()` can take a couple of seconds
and because it is executed outside of the main-thread, other message can be printed bevore
the IP address and UUID are ready to be printed.
2023-03-04 12:36:20 +01:00
ceze88 e57cd93629 Merge branch 'development' 2023-01-25 17:34:07 +01:00
ceze88 386ff209a7 Release v2.6.18 2023-01-25 16:02:44 +01:00
ceze88 7c02457108 Ignore self compiled plugins 2023-01-15 12:23:56 +01:00
Christian Koop c29c4a5b09
Release v2.6.18-DEV 2023-01-11 22:00:36 +01:00
ceze88 ad6b52ca4a Add license stuff 2023-01-11 21:41:04 +01:00
Christian Koop dc64c29da7
Ensures UTF-8 usage in LootManager
Probably doesn't affect anything as this file should only contain english letters
but just in case for the sake of tidyness
2023-01-08 12:47:27 +01:00
Christian Koop 339a4d6f6c
Ensures usage of UTF-8 in SongodaYamlConfig
Depending on the environment the default system charset might not be UTF-8 beaking
messages files using non-english language etc.

I'm not sure but Spigot might even set it to ASCII? The tests succeed locally because I am
using Manjaro Linux which uses UTF-8 by default in the JVM. But testing a plugin and logging
the default charset returns ASCII instead (on the same machine).
2023-01-08 12:46:42 +01:00
ceze88 336c5c49f3
Revert "License system"
This reverts commit 10aac8c10f.
2023-01-06 14:02:32 +01:00
ceze88 10aac8c10f License system 2023-01-02 13:39:54 +01:00
ceze88 bd187c7512 Fix max stack size for drops 2022-12-31 20:42:03 +01:00
Christian Koop 842841cd74
Fixes NMS for Spigot 1.19.0 / 1.19.1 / 1.19.2 detection
Purpur-Spigot and plain Spigot do not end with `.0`. Not sure if Paper does or Spigot 1.19.1 does?

I just added the plain `1.19` check.
This is not an issue in the Core v3 branch as the check is more stable there.
2022-12-30 20:09:01 +01:00
Christian Koop 5f762c9417
pom.xml: Updates and fixes test setup
Pitest was unable to run because it could not find a couple of NMS classes and some other stuff.

We are excluding the `SongodaCoreConstantsTest` because it apparently
sees the Skip-Exception we are throwing as a failed test instead of a skipped one.
Causing it to abort its whole operation – Probably just a bug in Pitest

I also added the groupId to the two maven/test plugins as they were missing.
I wondered a couple of times why InjtelliJ cannot detect them while `mvn` runs as expected.
Looks like I never realised that missing - Now it is like it should have been
2022-12-30 18:27:13 +01:00
Christian Koop e44e161c89
Adds some additional test cases for MathUtilsTest 2022-12-30 18:23:02 +01:00
Christian Koop ef6c37b80c
Improve test coverage + stability of configuration.yaml/songoda classes 2022-12-30 18:22:11 +01:00
Christian Koop 45e1319f9c
Remove some unused imports inside `v1_19_R2` module 2022-12-30 16:24:53 +01:00
Christian Koop 7975f9088d
Heavily refactor PlotSquaredProtection.class
Moved code into private methods to make the Location#at call more readable
and to reduce duplicate code.

`PlotSquared.get()` is marked as `@NotNull` and is never null
if `PlotSquaredProtection#isEnabled` returns true.
That's why I removed the `null` check on the *API* with a check if PlotSquared is enabled.

I replaced the usage of Java StreamAPI with a simple for loop for better potential performance.
The loop is so simple and we don't know the plugins that might be using this class,
thus greater performance for a small loss on readability is probably worth it

+ Removed some unused imports
2022-12-30 16:14:08 +01:00
Christian Koop 3a95b13419
Removes commented-out test-dependency `MockBukkit`
More details can be found in 404a94c307
2022-12-30 15:28:25 +01:00
Christian Koop 0a7b24c0ce
Updates dev dependency `org.jetbrains:annotations` to v23.1.0 2022-12-30 15:24:08 +01:00
Christian Koop 88e28689f7
Adds ConfigEntry#withDefaultValue for easier chaining
This allows to chain the default value instead of using the setter or constructor.
Long keys/values can be put into individual lines which improves readability.

In the future, we might want to have a Builder class that contains all thise #with methods
2022-12-30 15:21:07 +01:00
Christian Koop 7eff3c86ec
Code cleanup (rename e->ex in catch; better type for #withUpgradeStep) 2022-12-30 15:21:07 +01:00
ceze88 ea10cc2e3f Don't override uuid 2022-12-29 17:26:23 +01:00
ceze88 a554934bfa Remove deprecated constructor 2022-12-29 13:49:34 +01:00
ceze88 8f95056e31 A little database utility 2022-12-29 13:49:04 +01:00
Christian Koop f38296e4b1
GitHub Actions: Adds Spigot 1.18 + 1.19.3 to SonarCloud 2022-12-29 12:24:05 +01:00
ceze88 7674a86513 Merge branch 'development' of https://github.com/songoda/SongodaCore into development 2022-12-29 11:52:25 +01:00
ceze88 7ac9b7b283 Remove UUID when deserialising NBT 2022-12-29 11:52:12 +01:00
ceze88 8ad3bc8ba6 Why spihot api wasn't there? 2022-12-29 11:51:23 +01:00
ceze88 17fb03f073 Fix pre stacking items 2022-12-29 11:50:51 +01:00
Christian Koop dcd6967828
GitHub Actions: Adds Spigot 1.19.3 to the setup-action to compile it 2022-12-29 11:28:17 +01:00
Christian Koop c728c5fcc7
GitHub Actions: Adds Spigot 1.19.3 to the setup-action to compile it 2022-12-29 11:25:54 +01:00
Christian Koop 396f3aefb8
Merge branch 'development' into development-v3 2022-12-26 21:03:31 +01:00
Christian Koop 1a911ee085
Release v2.6.17 2022-12-26 19:59:02 +01:00
Christian Koop 6d28fce312
Updates dependency `de.tr7zw:item-nbt-api` to support Minecraft 1.19.3 2022-12-26 19:58:33 +01:00
Christian Koop 64865873f9
Adds NMS module for Spigot 1.19.3 (v1_19_R2) support 2022-12-26 13:44:58 +01:00
Christian Koop 296f82f50e
Restore functionality of deprecated SQLite connection acquisition
If the connection is closed, no new SQLite connection is created in plugins still using the
deprecated method.


Introduced in 0ae9c6fcdb
2022-12-26 13:44:58 +01:00
Christian Koop c3fb050444
Updates dependency UltimateStacker to v2.3.2 2022-12-26 13:44:49 +01:00
Christian Koop d939489861
Use `1.18-R0.1-SNAPSHOT` instead of `1.18` in `NMS-v1_18_R1` module 2022-12-25 22:49:39 +01:00
Christian Koop 4d194ed92b
Rename constant into upper case to match code conventions 2022-11-26 20:40:57 +01:00
Christian Koop 0b2a253014
Fix typo in JavaDoc 2022-11-26 20:40:28 +01:00
Christian Koop 00789921a3
Revert "GitHub Actions: Skip automated tests when running SonarCloud"
This reverts commit 59f4adfc6f.

We need the tests to generate the test coverage report. Didn't think of that.
2022-11-26 20:27:20 +01:00
Christian Koop e2194e0dec
GitHub Actions: Adds missing empty line between steps in sonarcloud.yml 2022-11-26 20:26:01 +01:00
Christian Koop 8e91cc18eb
Makes SongodaYamlConfig#cannotCreateBackupCopyExceptionPrefix static
It already is `final`.
By making it static we reduce the memory required by each instance of the class.
2022-11-26 20:25:11 +01:00
Christian Koop bba5fa5f3e
Adds additional information for deprecations as JavaDocs 2022-11-26 20:24:14 +01:00
Christian Koop bc56347727
Fix order of modifiers in SongodaCore-class 2022-11-26 20:23:45 +01:00
Christian Koop 75b497a163
Add private constructor to SongodaCoreConstants to hide implicit one
The utility class only has static members - Nothing to gain from instantiating it other than confusion
2022-11-26 20:23:08 +01:00
Christian Koop 59f4adfc6f
GitHub Actions: Skip automated tests when running SonarCloud
The build pipeline already runs the tests. I think it makes sense to run SonarCloud's static
code analysis when the project can be compiled without errors.
2022-11-26 15:36:29 +01:00
Christian Koop 67a69e34e8
Make unit tests in LocaleFileManagerTest deterministic
The order in which files inside of a given directory are listed is not guaranteed in any way.
This causes tests to work on my machine but fail on out GitHub Actions CI/CD pipeline.
2022-11-26 15:31:43 +01:00
Christian Koop 6c6c3e950c
GitHub Actions: Enable build and sonarcloud workflow for v3-dev-branch 2022-11-26 00:01:00 +01:00
Christian Koop 5a7a3d052d
Cleanup YAML in `.github/dependabot.yml` 2022-11-25 23:59:56 +01:00
Christian Koop d710b2d2d5
Add unit test for SongodaYamlConfig persisting comments on key-upgrades 2022-11-16 02:29:41 +01:00
Christian Koop 02330b5ca7
Improve temporary file deletion in YamlConfig and FileManager tests
The SongodaYamlConfig might create a backup config file when upgrading a
configuration into a newer version.
This file would not get deleted in the old implementation
2022-11-16 02:14:45 +01:00
Christian Koop f8b3942de2
Adds hyphen before timestamp in file name, when creating backup YamlCfg 2022-11-16 02:03:41 +01:00
Christian Koop daa601688d
Updates SnakeYaml dependency from 1.30 to 1.33 2022-11-16 02:03:03 +01:00
Christian Koop e7da328dc6
Fix YamlConfiguration not dumping comments
Not sure when it broke, but now it's fixed.
2022-11-16 02:02:09 +01:00
Christian Koop 404a94c307
Move from MockBukkit to Mockito in automated tests
MockBukkit is not able to mock all of Bukkit's API
and broke with a change in PaperMC causing all our
current tests to fail. It is also version dependant.

But with Mockito you have to do everything manually right now.
No helping functionality (like creating a new mock player which automatically
will be returned in `Bukkit#getOnlinePlayers()`)

I took this opportunity to learn a bit about Mocking in Bukkit
and decided on Mockito.
It looks like we could easily write our own MockBukkit
alternative in the future.

I am not really happy how `Mockito#verify` works tho.
I find it annoying not to be able to directly assert
on the calls made to a method.
You have to create an InOrder instance first for the
mock and in the end verify with `Mockito#times(0)`/`Mockito#never()`
and `Mockito#any()` for each argument a method takes, to assert a total of n calls.
2022-11-15 22:49:09 +01:00
Christian Koop ceebf211b3
Change maven repository IDs in pom.xml
I've setup proxy repositories at https://songoda.sprax.dev/repo/
for all current Core v3 dependencies (except maven-central).
These updated IDs can now be used in `~/.m2/settings.xml`
to configure mirrors: https://maven.apache.org/guides/mini/guide-mirror-settings.html
2022-11-15 18:57:10 +01:00
Christian Koop 6aa9178321
Fix `ItemUtils#applyRandomEnchants` in Minecraft 1.19
The method needs a `RandomSource` instead of a normal Java `Random`.
The method reference has been updated but updating
its usage has been forgotten.

Sadly I do not really know where to properly
get an `RandomSource` instance without instanciating it myself.
2022-11-07 22:29:40 +01:00
Christian Koop aff3ea92f3
Fix wrong coreVersion in SongodaCore class 2022-11-07 22:19:19 +01:00
ceze88 e8c0e21ac2 Adds suppoert for PlotSquared and MariaDB for SQL 2022-11-04 12:28:20 +01:00
Christian Koop 31fde88c33
Fix ConcurrentModificationException in DropUtils for UltimateStacker
Related to 92c653d9be
2022-10-26 22:59:00 +02:00
Christian Koop 500ac98f84
Release 2.6.17-SNAPSHOT 2022-10-26 21:59:06 +02:00
Christian Koop 5f43578869
Fix NoSuchFieldError on Paper-Spigot 1.19.2 for SWorld#getLivingEntities
The field does not exist on Spigot (located in another class?).
But `#getEntities()` does exactly what we need and Paper-Spigot still has it.


SD-9374
SD-9377
SD-9392
SD-9401
2022-10-26 21:58:34 +02:00
Christian Koop b168ad0738
Provisional first implementation of the new localization system
It it not done yet. A lot of usability features are still missing.
Including a proper interface to interact with the whole
new system in the plugins.
2022-09-29 21:55:57 +02:00
Christian Koop 2e15ed5d28
Adds a simple http client
This is intended to standardize how we do these request in the core.
It doesn't do much but it will sufice for now to be used
in the new localization system.
2022-09-29 21:52:59 +02:00
Christian Koop 2860dffb83
Update Dependencies: Spigot, MockBukkit, JUnit, pitest-maven 2022-09-29 21:39:07 +02:00
ceze88 92c653d9be Add max stack size check when pre-stack items with US 2022-09-19 21:04:52 +02:00
ceze88 30d070cade Drop items stacked when UltimateStacker is present 2022-09-19 20:37:34 +02:00
ceze88 d11b32d8ea Update UltimateStacker version 2022-09-19 20:36:38 +02:00
Christian Koop 954c5024a9
Reverts 'GitHub-Actions: Force Spigot 1.19.2 recompilation'
d51f72977b
2022-09-04 19:43:28 +02:00
Christian Koop 8bbed0342e
Merge branch 'development' 2022-09-04 19:39:36 +02:00
Christian Koop e3b275b40d
Release v2.6.16 2022-09-04 19:31:58 +02:00
Christian Koop d51f72977b
GitHub-Actions: Force Spigot 1.19.2 recompilation
The non-mapped version is currently cached and thus not getting
recompiled. This is a temporary *fix* for that
2022-09-04 19:24:50 +02:00
l3st4tDevelopment 4800d69829
Add 1.19.2 to workflow 2022-09-03 03:01:17 -04:00
l3st4tDevelopment 72b4d49997
Added 1.19.2 spigot 2022-09-03 03:00:48 -04:00
BuildTools 9c47056b46 Version 2.6.16-DEV - Support for 1.19.1/2 spawners. 2022-09-03 01:03:27 -04:00
Christian Koop 1cd96b10c5
Remove overloading `WorldCore#getSpawner(CreatureSpawner)` 2022-08-28 19:19:48 +02:00
Christian Koop b07f67e0d6
Unify and cleanup all pom.xml-files
This also moves all the dependency declarations of the NMS modules
from the Core-Module to its own NMS-Module.
This module might get merged with the NMS-API module in the future.
2022-08-28 19:13:59 +02:00
Christian Koop fc2aefdd9e
Add full support for Minecraft 1.19.0, 1.19.1 and 1.19.2
Between 1.19.0 and 1.19.1 the NMS version did not change
although implementations changed
2022-08-28 18:43:20 +02:00
Christian Koop b3426a6a1a
Load NMS modules via Reflections instead of defining everything manually
This probably needs some additonal work but my idea
is that every NMS module has only one entry point.
This hopefully allows for as much freedom in version-specific
implementations as possible and allows for easily  loading them via Reflections.
2022-08-28 18:20:22 +02:00
Christian Koop e18db1d775
Removes depenency on NMSPlayerImpl for NmsWorldBorderImpl 2022-08-28 16:54:29 +02:00
Christian Koop e96cb5426d
Migrate v1_18_R1 NMS module to use remapped-spigot at compile-time 2022-08-28 16:54:29 +02:00
Christian Koop 9d7026ec27
Replace SWorldBorder implementation and move it into NMS modules 2022-08-28 16:54:29 +02:00
Christian Koop 5c15d66415
Deprecate MethodMapping class
I do not intend to update it to support another version.
All implementations using it should be recoded and use the NMS modules instead if needed
2022-08-27 22:43:07 +02:00
Christian Koop 43148032a2
Replace #setBlockFast implementation and move into NMS modules
We need to check if FabledSkyBlock actually needs this and if it can be removed from the Core.
I added a TODO-Comment for that.
2022-08-27 22:42:07 +02:00
Christian Koop 3d20f439e1
Replace #updateAdjacentComparators implementation(+ move to NMS modules) 2022-08-27 22:35:37 +02:00
Christian Koop b779194e3e
Adds `SongodaCore#getVersion` and deprecate `#getCoreLibraryVersion` 2022-08-25 08:37:46 +02:00
Christian Koop 163e4d9eaf
Fix error handling of SongodaYamlConfig#load(Reader) 2022-08-21 20:44:41 +02:00
Christian Koop eea951ecc6
Adds some deprecation notices to configuration.editor classes 2022-08-21 20:44:19 +02:00
Christian Koop 20b44327e0
Redo ConfigEntry abstraction 2022-08-21 20:42:16 +02:00
Christian Koop 72c96bc09a
Adds Contract annotation to CompatibleMaterial#getMaterial 2022-08-21 20:39:50 +02:00
Christian Koop 76b3dc6682
Dependabot: Configure the target branch to be `development` 2022-08-19 10:53:17 +02:00
Christian Koop 7b775a1db3
GitHub-Actions: Fix Discord webhook URL used 2022-08-19 10:52:49 +02:00
Christian Koop a06d27ab90
Version v3.0.0-SNAPSHOT 2022-08-19 10:06:58 +02:00
Christian Koop d5ddde3e08
Migrate CustomizableGui from old Config to SongodaYamlConfig 2022-08-18 23:09:21 +02:00
Christian Koop 20b7a353b8
Adds SongodaYamlConfig#getAsEntry(String) for convenience
If you are reading a config dynamically instead of fully creating it
with all the entries beforehand, this method can be used
to easily access the *converted/casted* values.
2022-08-18 23:08:58 +02:00
Christian Koop 78b6039d39
Add contract to `ConfigEntry#getString(String)` for non-null-argument
The contract basically says that if you provide a
non-null argument to the method, it cannot return
a null value.
2022-08-18 23:07:18 +02:00
Christian Koop 3a09c19dbb
Adds getter to ConfigEntry for List<String> 2022-08-18 23:06:22 +02:00
Christian Koop da3c89450e
Remove usage of Locale classes 2022-08-18 23:05:21 +02:00
Christian Koop 61b784b3e8
Merge branch 'development' into development-v3 2022-08-18 22:57:46 +02:00
Christian Koop 5e1f1b802c
Introduce new CI/CD pipeline using GitHub Actions
A lot is happening in this release!

tl;dr: GitHub Actions runs tests, compiles the project, signs the jar files, deploys them to the Maven repo; Pushing a git tag issues a release instead of snapshot deployment; -SNAPSHOT is always added to the version otherwise; Core Version is now injected by maven instead of manually updating it in one of the classes


We now use GitHub Actions to run automated tests, compile the project, sign the resulting jar files, and always deploy a version to the Maven repo.
By default, a snapshot release is published but by creating a git tag, a release deploy can be triggered.

Additionally the Core version is not manually updated in one of the classes but injected after compiling it.
I think I found the most stable and easiest way to do this in maven,
although I'd have wished for it to be easier and maybe not after the class file has already been created.
2022-08-07 19:33:38 +02:00
Fernando Pettinelli df5adc0d3d Merge branch 'development' 2022-07-03 03:40:01 -04:00
Christian Koop f3b5b7c889
Merge branch 'development' 2022-06-28 12:17:18 +02:00
Christian Koop 84515e7004
Minor code cleanup in SongodaYamlConfig constructor
keeps the logger effectively final + makes Codacity' static code analysis happy
2022-06-26 13:57:12 +02:00
Christian Koop ed7b454625
Fix Exception when calling #emergencyStop inside onPluginEnable 2022-06-26 13:46:38 +02:00
Christian Koop 73685b62dd
Mark overwritten and empty config methods in SongodaPlugin as deprecated
The methods should not be used
2022-06-26 13:46:35 +02:00
Christian Koop 7ef00bb8f9
Adjust log levels in SongodaYamlConfig
Level.FINER is currently not logged anthough the Logger is set to ALL and isLoggable returns true for FINER.

There's an bug existing bug report at Spigot: https://hub.spigotmc.org/jira/browse/SPIGOT-7018
2022-06-26 13:46:29 +02:00
Christian Koop 532d96f6c1
Add `adventure-api` to SongodaCore dependencies 2022-06-26 13:28:10 +02:00
Christian Koop b0f006aed0
Fix SongodaYamlConfig not creating parent directory when saving
Caused an IOException if the PluginDataDir didn't exist yet.
2022-06-26 13:26:13 +02:00
Christian Koop e7e3c3d21d
Disable test CompatibileMaterialTest#getMaterialForAllBukkitMaterials
It is highly version dependent and breaks often because of that
2022-06-26 13:25:10 +02:00
Christian Koop c9a48387de
Fix SongodaYamlConfigTest leaving created backup files in tmp dir 2022-06-26 13:24:16 +02:00
Christian Koop fce5c5c6a1
Remove Config related methods in SongodaPlugin
Escept for #getExtraConfigs which got renamed, the other methods are no longer required and have been removed.

Additionally the config methods defined by Bukkit's JavaPlugin class
have been overwritten with empty bodies.
This prevents the default behaviour trying to access stuff that's not there
or should not be considered a valid config to use.
2022-06-26 02:38:29 +02:00
Christian Koop 4bc0e991ab
Removes #getConsole in SongodaPlugin 2022-06-26 02:33:09 +02:00
Christian Koop eb10b3f70a
Introduce new SongodaYamlConfig and ConfigEntry classes
This introduces an additional abstraction layer on top of the YamlConfiguration.
This is the class that should normally be used by plugins.
2022-06-26 01:51:53 +02:00
Christian Koop 8310541b91
Fix ServerVersion#UNKNOWN being treated like a normal version
This is required for unit tests (especially the `Bukkit#getServer != null` check).
But it seems faulty to even trat an unknown version like a normal one.
2022-06-26 01:39:39 +02:00
Christian Koop 02ab8d4bb2
Fix YamlConfiguration dumping null values and empty tree nodes 2022-06-26 01:39:39 +02:00
Christian Koop 885cc9a87e
Fix `YamlConfiruration#getKeys("")` not returning root node keys 2022-06-26 01:39:39 +02:00
Christian Koop 2683bc12c0
Fix exception on loading empty file in YamlConfiguration 2022-06-26 01:39:39 +02:00
Christian Koop 2262652577
Make YamlConfiguration insertion-sorted
This ensured that the order of the keys is deterministic and be controlled by the developer.
2022-06-26 01:39:39 +02:00
Christian Koop f6e207cdda
Rename `IConfiguration#getOrDefault` to `#getOr` 2022-06-26 01:39:39 +02:00
Christian Koop 41bd5c633a
Adds Enum support to YamlConfiguration class (#41) 2022-04-27 23:34:27 +02:00
Christian Koop 8f15df3601
Removes the default implementations for #save(File) and #load(File)
Overwriting an implementing class quickly becomes a potential hassle as there is no guarantee how they  are implementend


#41
2022-04-27 23:31:53 +02:00
Christian Koop 6d6fa7210a
Replace Songoda's YAML Configuration wrapper with an own implementation
Because Spigot 1.18 still hasn't fixed a critical bug like PaperMC did, I recoded the current YAML Configuration classes and access SnakeYaml directly instead of using the Spigot wrapper.
This implementation approach also allows for adding node comments using the lib instead of some woodo string manipulation.


#41
// I might move this into my own library in the future, lets see :p
2022-04-27 21:42:20 +02:00
Christian Koop 2a037e2853
Update required snakeyaml version from 1.26 to 1.30 (#41)
We probably want to take a look at what Spigot 1.8 comes with and if we are compatible or if we want to shade the lib into the Core instead.

Maybe we can have some kind of automatic legacy system that downloads an addional jar automatically when an unsupported Spigot version is detected... Lets see what time brings
2022-04-27 21:42:20 +02:00
Christian Koop 5debcf20f9
Update `junit-jupiter` dependency from v.5.8.1 to v5.8.2 2022-04-15 18:34:54 +02:00
Christian Koop d1fafd301d
Configure pitest for mutation tests 2022-04-15 18:34:29 +02:00
Christian Koop aa3455d6ba
Merge branch 'development' 2022-03-18 14:47:29 +01:00
Christian Koop f43f1a1584
Merge branch 'development' 2022-01-21 17:44:21 +01:00
Fernando Pettinelli bc53dc22cc Merge branch 'development' 2021-12-22 18:07:33 -03:00
Fernando Pettinelli f57fca41f2 Merge branch 'development' 2021-12-20 19:37:22 -03:00
Christian Koop 7c7330b45e
Merge branch 'development' 2021-12-18 18:18:51 +01:00
Christian Koop e8aa3f2b78
Merge branch 'development' 2021-12-14 21:01:32 +01:00
Christian Koop 1f2f98710e
Merge branch 'development' 2021-12-11 15:40:48 +01:00
Christian Koop 7c778fc90a
Merge branch 'development' 2021-12-10 19:46:28 +01:00
Christian Koop f8946d8aea
Merge branch 'development' 2021-12-10 18:14:54 +01:00
Christian Koop 03e94cf8e6
Merge branch 'development' 2021-12-09 04:52:35 +01:00
Christian Koop 42cf648d6f
Merge branch 'development' 2021-12-07 17:20:45 +01:00
Christian Koop 52a6c46220
Merge branch 'development' 2021-12-02 20:30:46 +01:00
245 changed files with 9059 additions and 2120 deletions

10
.github/FUNDING.yml vendored
View File

@ -1,12 +1,2 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: songoda
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: [ 'https://songoda.com/songoda+' ]

View File

@ -0,0 +1,23 @@
name: Prepare Workspace
description: Prepares the workspace for compilation
inputs:
maven_username:
required: false
description: The username to use for the Maven server
maven_password:
required: false
description: The password to use for the Maven server
runs:
using: composite
steps:
- uses: songoda/GH-Commons/.github/actions/setup_workspace@master
with:
maven_username: ${{ inputs.maven_username }}
maven_password: ${{ inputs.maven_password }}
- uses: SpraxDev/Action-SpigotMC@v4
with:
versions: 1.18.1, 1.18.2, 1.19, 1.19.2, 1.19.3, 1.19.4
remapped: true

13
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,13 @@
version: 2
updates:
- package-ecosystem: maven
directory: /
target-branch: development
schedule:
interval: monthly
- package-ecosystem: github-actions
directory: /
target-branch: development
schedule:
interval: monthly

96
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,96 @@
name: Build
on:
push:
branches: [ master, development ]
tags:
- 'v*'
pull_request:
types: [ opened, synchronize, reopened ]
permissions: read-all
env:
DEPLOYMENT_POM_PATH: ./Core/dependency-reduced-pom.xml
DEPLOYMENT_ARTIFACT_DIR: ./Core/target
DEPLOYMENT_ARTIFACT_SELECTOR: SongodaCore-*.jar
jobs:
Tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Prepare Workspace
uses: ./.github/actions/setup_project_workspace
- name: Run tests
run: mvn -B clean test
Build:
name: Build + Deploy
runs-on: ubuntu-latest
needs: [ Tests ]
steps:
- uses: actions/checkout@v3
- name: Prepare Workspace
uses: ./.github/actions/setup_project_workspace
with:
maven_username: ${{ secrets.MAVEN_REPO_USERNAME }}
maven_password: ${{ secrets.MAVEN_REPO_PASSWORD }}
- name: Set project version
uses: songoda/GH-Commons/.github/actions/maven_set_project_version@master
with:
append_snapshot: ${{ github.ref_type == 'tag' && 'false' || 'true' }}
version: ${{ github.ref_type == 'tag' && github.ref_name || '' }}
increment_version: ${{ github.ref_type == 'tag' && '' || 'patch' }}
- name: Build with Maven
run: mvn -B -Duser.name="GitHub Actions on $GITHUB_REPOSITORY (id=$GITHUB_RUN_ID)" -DskipTests clean package
- name: Sign jar archives
uses: songoda/GH-Commons/.github/actions/sign_jars@master
with:
jar_file_selector: ${{ env.DEPLOYMENT_ARTIFACT_DIR }}/${{ env.DEPLOYMENT_ARTIFACT_SELECTOR }}
keystore_gpg_encrypted: ${{ secrets.JARSIGNER_KEYSTORE_ENCRYPTED }}
keystore_gpg_password: ${{ secrets.JARSIGNER_KEYSTORE_ENCRYPTED_PASSWORD }}
keystore_password: ${{ secrets.JARSIGNER_KEYSTORE_PASSWORD }}
- name: 'Upload Build Artifacts'
uses: actions/upload-artifact@v3
with:
name: ${{ github.event.repository.name }}
path: ${{ env.DEPLOYMENT_ARTIFACT_DIR }}/${{ env.DEPLOYMENT_ARTIFACT_SELECTOR }}
- name: Deploy to Maven repo
if: ${{ github.event_name == 'push' }}
uses: songoda/GH-Commons/.github/actions/maven_deploy@master
with:
repository_url: ${{ secrets.MAVEN_REPO_URL_RELEASES }}
repository_url_snapshots: ${{ secrets.MAVEN_REPO_URL_SNAPSHOTS }}
maven_pom_path: ${{ env.DEPLOYMENT_POM_PATH }}
maven_out_dir: ${{ env.DEPLOYMENT_ARTIFACT_DIR }}
- name: Deploy parent pom.xml to Maven repo
if: ${{ github.event_name == 'push' }}
uses: songoda/GH-Commons/.github/actions/maven_deploy@master
with:
repository_url: ${{ secrets.MAVEN_REPO_URL_RELEASES }}
repository_url_snapshots: ${{ secrets.MAVEN_REPO_URL_SNAPSHOTS }}
only_deploy_pom: true
maven_out_dir: ${{ env.DEPLOYMENT_ARTIFACT_DIR }}
discord_webhook:
name: Send Discord Webhook
runs-on: ubuntu-latest
needs: [ Tests, Build ]
if: ${{ always() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development' || github.ref_type == 'tag') }}
steps:
- uses: actions/checkout@v3
- name: Notify Webhook
uses: songoda/GH-Commons/.github/actions/discord_send_job_results@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
webhook_url: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }}

36
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: CodeQL
on:
push:
branches: [ master, development ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, development ]
schedule:
- cron: 30 18 * * 4
permissions:
actions: read
contents: read
security-events: write
jobs:
Analyze:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: java
- name: Prepare Workspace
uses: ./.github/actions/setup_project_workspace
- name: Build with Maven
run: mvn -B -DskipTests clean package
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@ -1,61 +0,0 @@
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Build SongodaCore
on:
push:
branches: [ master, development ]
pull_request:
types: [ opened, synchronize, reopened ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
# Checkout project files
- uses: actions/checkout@v2
# Setup Java
- uses: actions/setup-java@v2
with:
java-version: 17
distribution: adopt
cache: maven
# Build remapped Spigot versions
- uses: SpraxDev/Action-SpigotMC@v4
with:
versions: 1.18.2, 1.19
remapped: true
# Build project
- name: Build with Maven
run: 'mvn -B -Duser.name="GitHub Runner on $GITHUB_REPOSITORY (id=$GITHUB_RUN_ID)" clean package'
# Upload build artifacts
- name: 'Upload Build Artifact: SongodaCore-*.jar'
uses: actions/upload-artifact@v2
with:
name: SongodaCore-artifacts
path: ./Core/target/SongodaCore-*.jar
##
# Discord Webhook
# TODO: Extract into external Action for better reusability (and readability)
##
- name: 'Discord Webhook (Success)'
if: ${{ success() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development') }}
continue-on-error: true
run: |
curl -X POST --data "{\"content\":null,\"embeds\":[{\"title\":\"Build succeeded!\",\"description\":\"The build with the ID #$GITHUB_RUN_NUMBER has succeeded!\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",\"color\":5490477,\"fields\":[{\"name\":\"Branch\",\"value\":\"$GITHUB_REF\",\"inline\":true}],\"author\":{\"name\":\"$GITHUB_REPOSITORY\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY\",\"icon_url\":\"$GITHUB_SERVER_URL/songoda.png\"},\"footer\":{\"text\":\"Initiated by $GITHUB_ACTOR\",\"icon_url\":\"$GITHUB_SERVER_URL/$GITHUB_ACTOR.png\"}}],\"username\":\"OctoAgent\",\"avatar_url\":\"https://github.githubassets.com/images/modules/logos_page/Octocat.png\"}" --header 'Content-Type: application/json' $DISCORD_WEBHOOK
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }}
- name: 'Discord Webhook (Failure)'
if: ${{ failure() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development') }}
continue-on-error: true
run: |
curl -X POST --data "{\"content\":null,\"embeds\":[{\"title\":\"Build failed!\",\"description\":\"The build with the ID #$GITHUB_RUN_NUMBER has failed!\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",\"color\":15611419,\"fields\":[{\"name\":\"Branch\",\"value\":\"$GITHUB_REF\",\"inline\":true}],\"author\":{\"name\":\"$GITHUB_REPOSITORY\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY\",\"icon_url\":\"$GITHUB_SERVER_URL/songoda.png\"},\"footer\":{\"text\":\"Initiated by $GITHUB_ACTOR\",\"icon_url\":\"$GITHUB_SERVER_URL/$GITHUB_ACTOR.png\"}}],\"username\":\"OctoAgent\",\"avatar_url\":\"https://github.githubassets.com/images/modules/logos_page/Octocat.png\"}" --header "Content-Type:application/json" $DISCORD_WEBHOOK
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }}

View File

@ -3,46 +3,40 @@ name: SonarCloud
on:
push:
branches: [ master, development ]
pull_request:
types: [ opened, synchronize, reopened ]
workflow_dispatch:
permissions: read-all
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_ORGANIZATION: craftaro
SONAR_PROJECT_KEY: craftaro_SongodaCore
jobs:
build:
name: Build
Analyze:
runs-on: ubuntu-latest
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
steps:
# Checkout project files
- uses: actions/checkout@v2
if: ${{ env.SONAR_TOKEN != null }}
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
fetch-depth: 0
# Setup Java
- uses: actions/setup-java@v2
if: ${{ env.SONAR_TOKEN != null }}
with:
java-version: 17
distribution: adopt
cache: maven
- name: Prepare Workspace
uses: ./.github/actions/setup_project_workspace
# Cache
- name: 'Cache: SonarCloud'
if: ${{ env.SONAR_TOKEN != null }}
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
# Build remapped Spigot versions
- uses: SpraxDev/Action-SpigotMC@v4
with:
versions: 1.18.2, 1.19
remapped: true
- name: Analyze project
if: ${{ env.SONAR_TOKEN != null }}
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=songoda_SongodaCore
run: >
mvn -B \
verify \
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \
-Dsonar.host.url=https://sonarcloud.io \
"-Dsonar.organization=$SONAR_ORGANIZATION" \
"-Dsonar.projectKey=$SONAR_PROJECT_KEY"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -7,18 +7,16 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore-Compatibility</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.18-R0.1-SNAPSHOT</version>
<version>1.19.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>

View File

@ -1,5 +1,9 @@
package com.songoda.core.compatibility;
/**
* @deprecated Usage is highly discouraged use com.songoda.core.nms.Nms#getImplementations() instead
*/
@Deprecated
public enum ClassMapping {
BIOME_BASE("world.level.biome", "BiomeBase"),
BIOME_STORAGE("world.level.chunk", "BiomeStorage"),
@ -47,6 +51,7 @@ public enum ClassMapping {
CRAFT_PLAYER("entity", "CraftPlayer"),
CRAFT_WORLD("CraftWorld"),
SINGLE_THREADED_RANDOM_SOURCE("world.level.levelgen", "SingleThreadedRandomSource"),
RANDOM_SOURCE("util", "RandomSource"),
MOJANGSON_PARSER("nbt", "MojangsonParser");

View File

@ -5,6 +5,7 @@ import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -32,6 +33,12 @@ public enum CompatibleMaterial {
DARK_OAK_DOOR_ITEM(431),
*/
/* 1.19.3 */
ENDER_DRAGON_SPAWN_EGG(),
IRON_GOLEM_SPAWN_EGG(),
SNOW_GOLEM_SPAWN_EGG(),
WITHER_SPAWN_EGG(),
/* 1.19 */
ACACIA_CHEST_BOAT(),
ALLAY_SPAWN_EGG(),
@ -1542,6 +1549,7 @@ public enum CompatibleMaterial {
*
* @return LegacyMaterial or null if none found
*/
@Contract("_, !null -> !null")
public static CompatibleMaterial getMaterial(String name, CompatibleMaterial def) {
return name == null ? def : lookupMap.getOrDefault(name.toUpperCase(), def);
}

View File

@ -5,6 +5,10 @@ import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Method;
/**
* @deprecated Usage is highly discouraged use com.songoda.core.nms.Nms#getImplementations() instead
*/
@Deprecated
public enum MethodMapping {
MC_ITEM_STACK__GET_TAG("getTag", "getTag", "s", "t", "u"),
MC_ITEM_STACK__SET_TAG("setTag", "setTag", "c", "c", "c", ClassMapping.NBT_TAG_COMPOUND.getClazz()),

View File

@ -6,26 +6,27 @@ import org.bukkit.Bukkit;
public enum ServerVersion {
UNKNOWN, V1_7, V1_8, V1_9, V1_10, V1_11, V1_12, V1_13, V1_14, V1_15, V1_16, V1_17, V1_18, V1_19, V1_20, V1_21;
private final static String serverPackagePath;
private final static String serverPackageVersion;
private final static String serverReleaseVersion;
private final static ServerVersion serverVersion;
private final static boolean isMocked;
static {
String srvPackage = Bukkit.getServer().getClass().getPackage().getName();
isMocked = srvPackage.equals("be.seeseemelk.mockbukkit");
if (Bukkit.getServer() != null) {
String srvPackage = Bukkit.getServer().getClass().getPackage().getName();
isMocked = srvPackage.equals("be.seeseemelk.mockbukkit");
if (isMocked) {
String packageVersionShard = "v" + Bukkit.getServer().getBukkitVersion().replace('.', '_') + "_R0";
serverPackagePath = "org.bukkit.craftbukkit." + packageVersionShard;
serverPackageVersion = packageVersionShard;
serverReleaseVersion = "0";
if (isMocked) {
serverPackageVersion = "v" + Bukkit.getServer().getBukkitVersion().replace('.', '_') + "_R0";
serverReleaseVersion = "0";
} else {
serverPackageVersion = srvPackage.substring(srvPackage.lastIndexOf('.') + 1);
serverReleaseVersion = serverPackageVersion.indexOf('R') != -1 ? serverPackageVersion.substring(serverPackageVersion.indexOf('R') + 1) : "";
}
} else {
serverPackagePath = srvPackage;
serverPackageVersion = serverPackagePath.substring(serverPackagePath.lastIndexOf('.') + 1);
serverReleaseVersion = serverPackageVersion.indexOf('R') != -1 ? serverPackageVersion.substring(serverPackageVersion.indexOf('R') + 1) : "";
serverPackageVersion = "Bukkit-not-initialized";
serverReleaseVersion = "Bukkit-not-initialized";
isMocked = false;
}
serverVersion = getVersion();
@ -42,18 +43,34 @@ public enum ServerVersion {
}
public boolean isLessThan(ServerVersion other) {
if (serverVersion == UNKNOWN) {
return false;
}
return this.ordinal() < other.ordinal();
}
public boolean isAtOrBelow(ServerVersion other) {
if (serverVersion == UNKNOWN && other != UNKNOWN) {
return false;
}
return this.ordinal() <= other.ordinal();
}
public boolean isGreaterThan(ServerVersion other) {
if (serverVersion == UNKNOWN) {
return false;
}
return this.ordinal() > other.ordinal();
}
public boolean isAtLeast(ServerVersion other) {
if (serverVersion == UNKNOWN && other != UNKNOWN) {
return false;
}
return this.ordinal() >= other.ordinal();
}
@ -78,18 +95,34 @@ public enum ServerVersion {
}
public static boolean isServerVersionAbove(ServerVersion version) {
if (serverVersion == UNKNOWN) {
return false;
}
return serverVersion.ordinal() > version.ordinal();
}
public static boolean isServerVersionAtLeast(ServerVersion version) {
if (serverVersion == UNKNOWN && version != UNKNOWN) {
return false;
}
return serverVersion.ordinal() >= version.ordinal();
}
public static boolean isServerVersionAtOrBelow(ServerVersion version) {
if (serverVersion == UNKNOWN && version != UNKNOWN) {
return false;
}
return serverVersion.ordinal() <= version.ordinal();
}
public static boolean isServerVersionBelow(ServerVersion version) {
if (serverVersion == UNKNOWN) {
return false;
}
return serverVersion.ordinal() < version.ordinal();
}
}

View File

@ -1,32 +0,0 @@
package com.songoda.core.compatibility.bukkit;
import be.seeseemelk.mockbukkit.MockBukkit;
import com.songoda.core.compatibility.CompatibleSound;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class CompatibleSoundTest {
@BeforeEach
void setUp() {
MockBukkit.mock();
}
@AfterEach
void tearDown() {
MockBukkit.unmock();
}
@Test
@Disabled("CompatibleSound class needs some work beforehand")
void getSound() {
for (CompatibleSound compatibleSound : CompatibleSound.values()) {
assertNotNull(compatibleSound.getSound());
// compatibleSound.usesCompatibility()
}
}
}

View File

@ -7,27 +7,37 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore</artifactId>
<packaging>jar</packaging>
<build>
<finalName>SongodaCore-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<groupId>de.m3y.maven</groupId>
<artifactId>inject-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>inject</goal>
</goals>
</execution>
</executions>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<release>${java.release}</release>
<injections>
<injection>
<value>${project.version}</value>
<pointCut>com.songoda.core.SongodaCoreConstants.getCoreVersion</pointCut>
</injection>
</injections>
</configuration>
</plugin>
@ -63,7 +73,19 @@
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>false</createDependencyReducedPom>
<useDependencyReducedPomInJar>true</useDependencyReducedPomInJar>
<artifactSet>
<includes>
<include>com.songoda:*</include>
<include>com.zaxxer:HikariCP</include>
<include>de.tr7zw:item-nbt-api</include>
<include>net.kyori:*</include>
<include>org.apache.commons:commons-lang3</include>
<include>org.apache.commons:commons-text</include>
<include>org.yaml:snakeyaml</include>
</includes>
</artifactSet>
<relocations>
<relocation>
@ -76,21 +98,30 @@
<shadedPattern>com.songoda.core.third_party.de.tr7zw.nbtapi</shadedPattern>
</relocation>
<relocation>
<pattern>net.kyori</pattern>
<shadedPattern>com.songoda.core.third_party.net.kyori</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.commons</pattern>
<shadedPattern>com.songoda.core.third_party.org.apache.commons</shadedPattern>
</relocation>
<relocation>
<pattern>org.yaml.snakeyaml</pattern>
<shadedPattern>com.songoda.core.third_party.org.yaml.snakeyaml</shadedPattern>
</relocation>
</relocations>
<artifactSet>
<includes>
<include>com.songoda:*</include>
<include>com.zaxxer:HikariCP</include>
<include>org.apache.commons:commons-text</include>
<include>org.apache.commons:commons-lang3</include>
<include>de.tr7zw:item-nbt-api</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<includes>
<include>**/*.class</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
@ -98,11 +129,23 @@
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.intellectualsites.bom</groupId>
<artifactId>bom-1.18.x</artifactId>
<version>1.18</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.17</version>
<version>1.19.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@ -113,137 +156,47 @@
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.10.0</version>
<scope>compile</scope>
</dependency>
<!-- Need to include all NMS modules here -->
<!-- Note when adding a new module: include the class in NmsManager -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-API</artifactId>
<version>${project.version}</version>
<version>2.11.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_8_R1</artifactId>
<version>${project.version}</version>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.11.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_8_R2</artifactId>
<version>${project.version}</version>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_8_R3</artifactId>
<version>${project.version}</version>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_9_R1</artifactId>
<version>${project.version}</version>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.33</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_9_R2</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_10_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_11_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_12_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_13_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_13_R2</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_14_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_15_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_16_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_16_R2</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_16_R3</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_17_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_18_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_18_R2</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-v1_19_R1</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<!-- End NMS -->
<!-- Start Plugin Hooks -->
<dependency>
@ -305,7 +258,7 @@
<dependency>
<groupId>com.songoda</groupId>
<artifactId>UltimateStacker</artifactId>
<version>2.1.1</version>
<version>2.3.2</version>
<scope>provided</scope>
</dependency>
@ -352,9 +305,9 @@
</dependency>
<dependency>
<groupId>me.angeschossen</groupId>
<groupId>com.github.Angeschossen</groupId>
<artifactId>LandsAPI</artifactId>
<version>4.12.20</version>
<version>6.28.11</version>
<scope>provided</scope>
</dependency>
@ -365,6 +318,24 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.plotsquared</groupId>
<artifactId>PlotSquared-Core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.plotsquared</groupId>
<artifactId>PlotSquared-Bukkit</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>PlotSquared-Core</artifactId>
<groupId>*</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.songoda</groupId>
<artifactId>UltimateClaims</artifactId>
@ -400,41 +371,5 @@
<scope>provided</scope>
</dependency>
<!-- End Plugin Hooks -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.26</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.23.1</version>
</dependency>
</dependencies>
</project>

View File

@ -8,6 +8,8 @@ import com.songoda.core.core.PluginInfo;
import com.songoda.core.core.PluginInfoModule;
import com.songoda.core.core.SongodaCoreCommand;
import com.songoda.core.core.SongodaCoreDiagCommand;
import com.songoda.core.core.SongodaCoreIPCommand;
import com.songoda.core.core.SongodaCoreUUIDCommand;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -42,27 +44,36 @@ import java.util.logging.Level;
import java.util.logging.Logger;
public class SongodaCore {
private final static Logger logger = Logger.getLogger("SongodaCore");
private static final Logger logger = Logger.getLogger(SongodaCoreConstants.getProjectName());
/**
* Whenever we make a major change to the core GUI, updater,
* or other function used by the core, increment this number
*
* @deprecated The Core's version should be used instead as it uses Semantic Versioning
*/
private final static int coreRevision = 9;
@Deprecated
private static final int coreRevision = 9;
/**
* @since coreRevision 6
* @deprecated Is being replaced by {@link SongodaCoreConstants#getCoreVersion()} which is automatically kept up to date.
*/
private final static String coreVersion = "2.6.14-DEV";
@Deprecated
private static final String coreVersion = SongodaCoreConstants.getCoreVersion();
/**
* This is specific to the website api
*
* @deprecated Seems useless and will probably be removed in the near future
*/
private final static int updaterVersion = 1;
@Deprecated
private static final int updaterVersion = 1;
private final static Set<PluginInfo> registeredPlugins = new HashSet<>();
private static final Set<PluginInfo> registeredPlugins = new HashSet<>();
private static SongodaCore INSTANCE = null;
private JavaPlugin piggybackedPlugin;
private CommandManager commandManager;
private EventListener loginListener;
@ -74,7 +85,7 @@ public class SongodaCore {
}
public static void registerPlugin(JavaPlugin plugin, int pluginID, CompatibleMaterial icon) {
registerPlugin(plugin, pluginID, icon == null ? "STONE" : icon.name(), coreVersion);
registerPlugin(plugin, pluginID, icon == null ? "STONE" : icon.name(), SongodaCoreConstants.getCoreVersion());
}
public static void registerPlugin(JavaPlugin plugin, int pluginID, String icon) {
@ -89,13 +100,23 @@ public class SongodaCore {
try {
// test to see if we're up-to-date
int otherVersion;
int ownVersion;
try {
otherVersion = (int) clazz.getMethod("getCoreVersion").invoke(null);
otherVersion = (int) clazz.getMethod("getCoreMajorVersion").invoke(null);
ownVersion = getCoreMajorVersion();
} catch (Exception ignore) {
otherVersion = -1;
try {
otherVersion = (int) clazz.getMethod("getCoreVersion").invoke(null);
} catch (Exception ignore2) {
otherVersion = -1;
}
ownVersion = getCoreVersion();
}
if (otherVersion >= getCoreVersion()) {
if (otherVersion >= ownVersion) {
// use the active service
// assuming that the other is greater than R6 if we get here ;)
clazz.getMethod("registerPlugin", JavaPlugin.class, int.class, String.class, String.class).invoke(null, plugin, pluginID, icon, coreVersion);
@ -172,7 +193,7 @@ public class SongodaCore {
private void init() {
shadingListener = new ShadedEventListener();
commandManager.registerCommandDynamically(new SongodaCoreCommand())
.addSubCommand(new SongodaCoreDiagCommand());
.addSubCommands(new SongodaCoreDiagCommand(), new SongodaCoreIPCommand(), new SongodaCoreUUIDCommand());
Bukkit.getPluginManager().registerEvents(loginListener, piggybackedPlugin);
Bukkit.getPluginManager().registerEvents(shadingListener, piggybackedPlugin);
@ -219,6 +240,10 @@ public class SongodaCore {
tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> update(info), 60L));
}
/**
* @deprecated Seems useless and will probably be replaced in the near future
*/
@Deprecated
private void update(PluginInfo plugin) {
try {
URL url = new URL("https://update.songoda.com/index.php?plugin=" + plugin.getSongodaId()
@ -264,20 +289,45 @@ public class SongodaCore {
return new ArrayList<>(registeredPlugins);
}
public static String getVersion() {
return SongodaCoreConstants.getCoreVersion();
}
/**
* @deprecated Use {@link #getCoreMajorVersion()} instead, but careful, coreRevision is at 9 while major version is at 2
*/
@Deprecated
public static int getCoreVersion() {
return coreRevision;
}
/**
* @deprecated Use {@link #getVersion()} instead
*/
@Deprecated
public static String getCoreLibraryVersion() {
return coreVersion;
return SongodaCoreConstants.getCoreVersion();
}
public static int getCoreMajorVersion() {
String fullVersion = getVersion();
if (fullVersion.contains(".")) {
return Integer.parseInt(fullVersion.substring(0, fullVersion.indexOf(".")));
}
return -1;
}
/**
* @deprecated Seems useless and will probably be removed in the near future
*/
@Deprecated
public static int getUpdaterVersion() {
return updaterVersion;
}
public static String getPrefix() {
return "[SongodaCore] ";
return "[" + SongodaCoreConstants.getProjectName() + "] ";
}
public static Logger getLogger() {

View File

@ -0,0 +1,26 @@
package com.songoda.core;
/**
* Some return values in this class are automatically replaced by a maven plugin after the project has been compiled.
* This allows for properties to be defined at one place without relying on a text file
* that needs to be inside the final jar (might get lost when this lib is shaded into other projects).
* <p>
* <b>!! Manually changing the values in this class has to be considered a breaking change. !!</b>
*/
public class SongodaCoreConstants {
private SongodaCoreConstants() {
throw new IllegalStateException("Utility class");
}
public static String getCoreVersion() {
return "UNKNOWN_VESION";
}
public static String getProjectName() {
return "SongodaCore";
}
public static String getGitHubProjectUrl() {
return "https://github.com/craftaro/SongodaCore";
}
}

View File

@ -4,10 +4,11 @@ import com.songoda.core.configuration.Config;
import com.songoda.core.database.DataManagerAbstract;
import com.songoda.core.locale.Locale;
import com.songoda.core.utils.Metrics;
import com.songoda.core.utils.SongodaAuth;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
@ -24,7 +25,6 @@ public abstract class SongodaPlugin extends JavaPlugin {
protected Config config = new Config(this);
protected long dataLoadDelay = 20L;
protected ConsoleCommandSender console = Bukkit.getConsoleSender();
private boolean emergencyStop = false;
static {
@ -84,29 +84,61 @@ public abstract class SongodaPlugin extends JavaPlugin {
@Override
public final void onEnable() {
if (emergencyStop) {
if (this.emergencyStop) {
setEnabled(false);
return;
}
CommandSender console = Bukkit.getConsoleSender();
// Check plugin access, don't load plugin if user don't have access
if (!SongodaAuth.isAuthorized(true)) {
String pluginName = getDescription().getName();
new Thread(() -> {
String externalIP = SongodaAuth.getIP();
String serverUuid = SongodaAuth.getUUID().toString();
String message = "\n" +
ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
ChatColor.RED + "You do not have access to the " + pluginName + " plugin.\n" +
ChatColor.YELLOW + "Please purchase a license at https://sngda.to/marketplace\n" +
ChatColor.YELLOW + "or set up your license at https://sngda.to/licenses\n" +
ChatColor.YELLOW + "License setup steps:\n" +
ChatColor.YELLOW + "Visit the link mentioned above and click the 'Create License' button.\n" +
ChatColor.YELLOW + "Copy the following IP address and UUID and click create.\n" +
ChatColor.YELLOW + "UUID: " + serverUuid + "\n" +
ChatColor.YELLOW + "IP: " + externalIP + "\n" +
ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
console.sendMessage(message);
}).start();
emergencyStop();
return;
}
console.sendMessage(" "); // blank line to separate chatter
console.sendMessage(ChatColor.GREEN + "=============================");
console.sendMessage(String.format("%s%s %s by %sSongoda <3!", ChatColor.GRAY,
console.sendMessage(String.format("%s%s %s by %sCraftaro <3!", ChatColor.GRAY,
getDescription().getName(), getDescription().getVersion(), ChatColor.DARK_PURPLE));
console.sendMessage(String.format("%sAction: %s%s%s...", ChatColor.GRAY,
ChatColor.GREEN, "Enabling", ChatColor.GRAY));
try {
locale = Locale.loadDefaultLocale(this, "en_US");
this.locale = Locale.loadDefaultLocale(this, "en_US");
// plugin setup
onPluginEnable();
// Load Data.
Bukkit.getScheduler().runTaskLater(this, this::onDataLoad, dataLoadDelay);
if (this.emergencyStop) {
return;
}
if (emergencyStop) {
// Load Data.
Bukkit.getScheduler().runTaskLater(this, this::onDataLoad, this.dataLoadDelay);
if (this.emergencyStop) {
console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
console.sendMessage(" ");
return;
@ -129,13 +161,15 @@ public abstract class SongodaPlugin extends JavaPlugin {
@Override
public final void onDisable() {
if (emergencyStop) {
if (this.emergencyStop) {
return;
}
CommandSender console = Bukkit.getConsoleSender();
console.sendMessage(" "); // blank line to separate chatter
console.sendMessage(ChatColor.GREEN + "=============================");
console.sendMessage(String.format("%s%s %s by %sSongoda <3!", ChatColor.GRAY,
console.sendMessage(String.format("%s%s %s by %sCraftaro <3!", ChatColor.GRAY,
getDescription().getName(), getDescription().getVersion(), ChatColor.DARK_PURPLE));
console.sendMessage(String.format("%sAction: %s%s%s...", ChatColor.GRAY,
ChatColor.RED, "Disabling", ChatColor.GRAY));
@ -146,12 +180,8 @@ public abstract class SongodaPlugin extends JavaPlugin {
console.sendMessage(" "); // blank line to separate chatter
}
public ConsoleCommandSender getConsole() {
return console;
}
public Locale getLocale() {
return locale;
return this.locale;
}
/**
@ -164,13 +194,13 @@ public abstract class SongodaPlugin extends JavaPlugin {
* @return true if the locale exists and was loaded successfully
*/
public boolean setLocale(String localeName, boolean reload) {
if (locale != null && locale.getName().equals(localeName)) {
return !reload || locale.reloadMessages();
if (this.locale != null && this.locale.getName().equals(localeName)) {
return !reload || this.locale.reloadMessages();
}
Locale l = Locale.loadLocale(this, localeName);
if (l != null) {
locale = l;
this.locale = l;
return true;
}
@ -209,13 +239,13 @@ public abstract class SongodaPlugin extends JavaPlugin {
if (unfinishedTasks > 0) {
getLogger().log(Level.WARNING,
String.format("A DataManager has been forcefully terminated with %d unfinished tasks - " +
"This can be a serious problem, please report it to us (Songoda)!", unfinishedTasks));
"This can be a serious problem, please report it to us (Craftaro / Songoda)!", unfinishedTasks));
}
}
}
protected void emergencyStop() {
emergencyStop = true;
this.emergencyStop = true;
Bukkit.getPluginManager().disablePlugin(this);
}
@ -228,10 +258,10 @@ public abstract class SongodaPlugin extends JavaPlugin {
protected void criticalErrorOnPluginStartup(Throwable th) {
Bukkit.getLogger().log(Level.SEVERE,
String.format(
"Unexpected error while loading %s v%s c%s: Disabling plugin!",
"Unexpected error while loading %s v%s (core v%s): Disabling plugin!",
getDescription().getName(),
getDescription().getVersion(),
SongodaCore.getCoreLibraryVersion()
SongodaCore.getVersion()
), th);
emergencyStop();

View File

@ -5,7 +5,7 @@ import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.songoda.core.compatibility.ClassMapping;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.Nms;
import com.songoda.core.utils.TextUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@ -13,7 +13,6 @@ import org.bukkit.entity.Player;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
@ -227,8 +226,8 @@ public class ChatMessage {
Object packet;
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_19)) {
packet = mc_PacketPlayOutChat_new.newInstance(mc_IChatBaseComponent_ChatSerializer_a.invoke(null, gson.toJson(textList)), mc_PacketPlayOutChat_new_1_19_0 ? 1 : true);
}else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16)) {
packet = mc_PacketPlayOutChat_new.newInstance(mc_IChatBaseComponent_ChatSerializer_a.invoke(null, gson.toJson(textList)), mc_PacketPlayOutChat_new_1_19_0 ? 1 : false);
} else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16)) {
packet = mc_PacketPlayOutChat_new.newInstance(
mc_IChatBaseComponent_ChatSerializer_a.invoke(null, gson.toJson(textList)),
mc_chatMessageType_Chat.get(null),
@ -237,8 +236,8 @@ public class ChatMessage {
packet = mc_PacketPlayOutChat_new.newInstance(mc_IChatBaseComponent_ChatSerializer_a.invoke(null, gson.toJson(textList)));
}
NmsManager.getPlayer().sendPacket((Player) sender, packet);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Nms.getImplementations().getPlayer().sendPacket((Player) sender, packet);
} catch (ReflectiveOperationException | IllegalArgumentException ex) {
Bukkit.getLogger().log(Level.WARNING, "Problem preparing raw chat packets (disabling further packets)", ex);
enabled = false;
}

View File

@ -372,6 +372,10 @@ public class CommandManager implements CommandExecutor, TabCompleter {
// Set tab complete
commandObject.setTabCompleter(tabManager);
if (command.equalsIgnoreCase("songoda")) {
commandObject.setAliases(Collections.singletonList("craftaro"));
}
// Register the command
Field fieldKnownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands");
fieldKnownCommands.setAccessible(true);

View File

@ -65,7 +65,7 @@ public class MainCommand extends AbstractCommand {
.sendTo(sender);
}
sender.sendMessage(ChatColor.DARK_GRAY + "- " + ChatColor.YELLOW + "/songoda" + ChatColor.GRAY + " - Opens the Songoda plugin GUI");
sender.sendMessage(ChatColor.DARK_GRAY + "- " + ChatColor.YELLOW + "/craftaro" + ChatColor.GRAY + " - Opens the Craftaro plugin GUI");
sender.sendMessage("");
if (nestedCommands != null) {

View File

@ -12,7 +12,7 @@ public class SongodaCoreCommand extends AbstractCommand {
protected GuiManager guiManager;
public SongodaCoreCommand() {
super(false, "songoda");
super(CommandType.CONSOLE_OK, "craftaro", "songoda");
}
@Override
@ -24,7 +24,9 @@ public class SongodaCoreCommand extends AbstractCommand {
guiManager.showGUI((Player) sender, new SongodaCoreOverviewGUI());
} else {
sender.sendMessage("/songoda diag");
sender.sendMessage("/craftaro diag");
sender.sendMessage("/craftaro myip");
sender.sendMessage("/craftaro uuid");
}
return ReturnType.SUCCESS;
@ -37,7 +39,7 @@ public class SongodaCoreCommand extends AbstractCommand {
@Override
public String getSyntax() {
return "/songoda";
return "/craftaro";
}
@Override

View File

@ -9,66 +9,26 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.DecimalFormat;
import java.util.List;
public class SongodaCoreDiagCommand extends AbstractCommand {
private final DecimalFormat format = new DecimalFormat("##.##");
private final DecimalFormat decimalFormat = new DecimalFormat("##.##");
private Object serverInstance;
private Field tpsField;
private Object nmsServerInstance;
private Field recentTpsOnNmsServer;
public SongodaCoreDiagCommand() {
super(false, "diag");
super(CommandType.CONSOLE_OK, "diag");
try {
serverInstance = ClassMapping.MINECRAFT_SERVER.getClazz().getMethod("getServer").invoke(null);
tpsField = serverInstance.getClass().getField("recentTps");
} catch (NoSuchFieldException | SecurityException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException ex) {
this.nmsServerInstance = ClassMapping.MINECRAFT_SERVER.getClazz().getMethod("getServer").invoke(null);
this.recentTpsOnNmsServer = this.nmsServerInstance.getClass().getField("recentTps");
} catch (ReflectiveOperationException | SecurityException | IllegalArgumentException ex) {
ex.printStackTrace();
}
}
@Override
protected ReturnType runCommand(CommandSender sender, String... args) {
sender.sendMessage("");
sender.sendMessage("Songoda Diagnostics Information");
sender.sendMessage("");
sender.sendMessage("Plugins:");
for (PluginInfo plugin : SongodaCore.getPlugins()) {
sender.sendMessage(plugin.getJavaPlugin().getName()
+ " (" + plugin.getJavaPlugin().getDescription().getVersion() + " Core " + plugin.getCoreLibraryVersion() + ")");
}
sender.sendMessage("");
sender.sendMessage("Server Version: " + Bukkit.getVersion());
sender.sendMessage("NMS: " + ServerProject.getServerVersion() + " " + ServerVersion.getServerVersionString());
sender.sendMessage("Operating System: " + System.getProperty("os.name"));
sender.sendMessage("Allocated Memory: " + format.format(Runtime.getRuntime().maxMemory() / (1024 * 1024)) + "Mb");
sender.sendMessage("Online Players: " + Bukkit.getOnlinePlayers().size());
if (tpsField != null) {
try {
double[] tps = ((double[]) tpsField.get(serverInstance));
sender.sendMessage("TPS from last 1m, 5m, 15m: " + format.format(tps[0]) + ", "
+ format.format(tps[1]) + ", " + format.format(tps[2]));
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
return ReturnType.SUCCESS;
}
@Override
protected List<String> onTab(CommandSender sender, String... args) {
return null;
}
@Override
public String getPermissionNode() {
return "songoda.admin";
@ -76,11 +36,60 @@ public class SongodaCoreDiagCommand extends AbstractCommand {
@Override
public String getSyntax() {
return "/songoda diag";
return "/craftaro diag";
}
@Override
public String getDescription() {
return "Display diagnostics information.";
}
@Override
protected ReturnType runCommand(CommandSender sender, String... args) {
sender.sendMessage("");
sender.sendMessage("Craftaro Diagnostics Information");
sender.sendMessage("");
sender.sendMessage("Plugins:");
for (PluginInfo plugin : SongodaCore.getPlugins()) {
sender.sendMessage(String.format("%s v%s (Core v%s)",
plugin.getJavaPlugin().getName(),
plugin.getJavaPlugin().getDescription().getVersion(),
plugin.getCoreLibraryVersion()));
}
sender.sendMessage("");
sender.sendMessage("Server Version: " + Bukkit.getVersion());
sender.sendMessage("NMS: " + ServerProject.getServerVersion() + " " + ServerVersion.getServerVersionString());
sender.sendMessage("Operating System: " + System.getProperty("os.name"));
sender.sendMessage("Allocated Memory: " + getRuntimeMaxMemory());
sender.sendMessage("Online Players: " + Bukkit.getOnlinePlayers().size());
sendCurrentTps(sender);
sender.sendMessage("");
return ReturnType.SUCCESS;
}
@Override
protected List<String> onTab(CommandSender sender, String... args) {
return null;
}
private String getRuntimeMaxMemory() {
return this.decimalFormat.format(Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " MiB";
}
private void sendCurrentTps(CommandSender receiver) {
if (this.recentTpsOnNmsServer == null) {
return;
}
try {
double[] tps = ((double[]) this.recentTpsOnNmsServer.get(this.nmsServerInstance));
receiver.sendMessage(String.format("TPS from last 1m, 5m, 15m: %s, %s, %s", this.decimalFormat.format(tps[0]), this.decimalFormat.format(tps[1]), this.decimalFormat.format(tps[2])));
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
}

View File

@ -0,0 +1,73 @@
package com.songoda.core.core;
import com.songoda.core.commands.AbstractCommand;
import com.songoda.core.utils.SongodaAuth;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class SongodaCoreIPCommand extends AbstractCommand {
public SongodaCoreIPCommand() {
super(CommandType.CONSOLE_OK, "myip");
}
@Override
protected ReturnType runCommand(CommandSender sender, String... args) {
Thread thread = new Thread(() -> {
String ip = SongodaAuth.getIP();
sender.sendMessage("");
sender.sendMessage("IP Information");
sender.sendMessage("");
if (sender instanceof Player) {
TextComponent component = new TextComponent("Your public IP is: " + ip);
component.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, ip));
component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[]{new TextComponent("Click to copy")}));
sender.spigot().sendMessage(component);
} else {
sender.sendMessage("Your public IP is: " + ip);
}
sender.sendMessage("");
});
thread.start();
return ReturnType.SUCCESS;
}
@Override
protected List<String> onTab(CommandSender sender, String... args) {
return null;
}
@Override
public String getPermissionNode() {
return "songoda.admin";
}
@Override
public String getSyntax() {
return "/craftaro myip";
}
@Override
public String getDescription() {
return "Displays your public IP address.";
}
}

View File

@ -16,7 +16,7 @@ final class SongodaCoreOverviewGUI extends Gui {
// could do pages, too, but don't think we'll have that many at a time for a while
int max = (int) Math.ceil(plugins.size() / 9.);
setRows(max);
setTitle("Songoda Plugins");
setTitle("Craftaro Plugins");
// TODO: this could use some decorating

View File

@ -0,0 +1,55 @@
package com.songoda.core.core;
import com.songoda.core.commands.AbstractCommand;
import com.songoda.core.utils.SongodaAuth;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.UUID;
public class SongodaCoreUUIDCommand extends AbstractCommand {
public SongodaCoreUUIDCommand() {
super(CommandType.CONSOLE_OK, "uuid");
}
@Override
protected ReturnType runCommand(CommandSender sender, String... args) {
sender.sendMessage("");
if (sender instanceof Player) {
TextComponent component = new TextComponent("Your server UUID is: " + SongodaAuth.getUUID());
component.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, SongodaAuth.getUUID().toString()));
component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new BaseComponent[]{new TextComponent("Click to copy")}));
sender.spigot().sendMessage(component);
} else {
sender.sendMessage("Your server UUID is: " + SongodaAuth.getUUID());
}
sender.sendMessage("");
return ReturnType.SUCCESS;
}
@Override
protected List<String> onTab(CommandSender sender, String... args) {
return null;
}
@Override
public String getPermissionNode() {
return "songoda.admin";
}
@Override
public String getSyntax() {
return "/craftaro uuid";
}
@Override
public String getDescription() {
return "Returns your server's uuid";
}
}

View File

@ -21,6 +21,7 @@ import java.util.function.Consumer;
public class DataManagerAbstract {
protected final DatabaseConnector databaseConnector;
protected final Plugin plugin;
protected final DatabaseType type;
protected final ExecutorService asyncPool = Executors.newSingleThreadExecutor();
@ -30,6 +31,7 @@ public class DataManagerAbstract {
public DataManagerAbstract(DatabaseConnector databaseConnector, Plugin plugin) {
this.databaseConnector = databaseConnector;
this.plugin = plugin;
this.type = databaseConnector.getType();
}
/**
@ -196,4 +198,11 @@ public class DataManagerAbstract {
});
});
}
public String getSyntax(String string, DatabaseType type) {
if (this.type == type) {
return string;
}
return "";
}
}

View File

@ -31,4 +31,6 @@ public interface DatabaseConnector {
}
Connection getConnection();
DatabaseType getType();
}

View File

@ -0,0 +1,8 @@
package com.songoda.core.database;
public enum DatabaseType {
MARIADB,
MYSQL,
SQLITE
}

View File

@ -0,0 +1,70 @@
package com.songoda.core.database;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.bukkit.plugin.Plugin;
import java.sql.Connection;
import java.sql.SQLException;
public class MariaDBConnector implements DatabaseConnector {
private final Plugin plugin;
private HikariDataSource hikari;
private boolean initializedSuccessfully;
public MariaDBConnector(Plugin plugin, String hostname, int port, String database, String username, String password, boolean useSSL, int poolSize) {
this.plugin = plugin;
plugin.getLogger().info("connecting to " + hostname + " : " + port);
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mariadb://" + hostname + ":" + port + "/" + database + "?useSSL=" + useSSL);
config.setUsername(username);
config.setPassword(password);
config.setMaximumPoolSize(poolSize);
try {
this.hikari = new HikariDataSource(config);
this.initializedSuccessfully = true;
} catch (Exception ex) {
this.initializedSuccessfully = false;
}
}
@Override
public boolean isInitialized() {
return this.initializedSuccessfully;
}
@Override
public void closeConnection() {
this.hikari.close();
}
@Deprecated
@Override
public void connect(DatabaseConnector.ConnectionCallback callback) {
try (Connection connection = this.hikari.getConnection()) {
callback.accept(connection);
} catch (SQLException ex) {
this.plugin.getLogger().severe("An error occurred executing a MySQL query: " + ex.getMessage());
ex.printStackTrace();
}
}
@Override
public Connection getConnection() {
try {
return this.hikari.getConnection();
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
@Override
public DatabaseType getType() {
return DatabaseType.MARIADB;
}
}

View File

@ -61,4 +61,9 @@ public class MySQLConnector implements DatabaseConnector {
}
return null;
}
@Override
public DatabaseType getType() {
return DatabaseType.MYSQL;
}
}

View File

@ -42,16 +42,8 @@ public class SQLiteConnector implements DatabaseConnector {
@Deprecated
@Override
public void connect(ConnectionCallback callback) {
if (this.connection == null) {
try {
this.connection = DriverManager.getConnection(this.connectionString);
} catch (SQLException ex) {
this.plugin.getLogger().severe("An error occurred retrieving the SQLite database connection: " + ex.getMessage());
}
}
try {
callback.accept(this.connection);
callback.accept(getConnection());
} catch (Exception ex) {
this.plugin.getLogger().severe("An error occurred executing an SQLite query: " + ex.getMessage());
ex.printStackTrace();
@ -73,4 +65,9 @@ public class SQLiteConnector implements DatabaseConnector {
}
return this.connection;
}
@Override
public DatabaseType getType() {
return DatabaseType.SQLITE;
}
}

View File

@ -2,7 +2,7 @@ package com.songoda.core.gui;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.gui.methods.Clickable;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.Nms;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.anvil.CustomAnvil;
import org.bukkit.entity.Player;
@ -125,7 +125,7 @@ public class AnvilGui extends Gui {
@Override
protected void createInventory() {
AnvilCore nms = NmsManager.getAnvil();
AnvilCore nms = Nms.getImplementations().getAnvil();
if (nms != null) {
anvil = nms.createAnvil(player, new GuiHolder(guiManager, this));

View File

@ -60,7 +60,7 @@ public class CustomizableGui extends Gui {
"in this GUI.")
.setDefaultComment("overrides",
"For information on how to apply overrides please visit",
"https://wiki.songoda.com/Gui");
"https://wiki.craftaro.com/index.php/Gui");
config.saveChanges();
}

View File

@ -1,8 +1,9 @@
package com.songoda.core.hooks.protection;
import me.angeschossen.lands.api.integration.LandsIntegration;
import me.angeschossen.lands.api.LandsIntegration;
import me.angeschossen.lands.api.flags.type.Flags;
import me.angeschossen.lands.api.flags.type.RoleFlag;
import me.angeschossen.lands.api.land.Area;
import me.angeschossen.lands.api.role.enums.RoleSetting;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
@ -13,32 +14,31 @@ public class LandsProtection extends Protection {
public LandsProtection(Plugin plugin) {
super(plugin);
this.landsIntegration = new LandsIntegration(plugin);
this.landsIntegration = LandsIntegration.of(plugin);
}
@Override
public boolean canPlace(Player player, Location location) {
return hasPerms(player, location, RoleSetting.BLOCK_PLACE);
return hasPerms(player, location, Flags.BLOCK_PLACE);
}
@Override
public boolean canBreak(Player player, Location location) {
return hasPerms(player, location, RoleSetting.BLOCK_BREAK);
return hasPerms(player, location, Flags.BLOCK_BREAK);
}
@Override
public boolean canInteract(Player player, Location location) {
return hasPerms(player, location, RoleSetting.INTERACT_CONTAINER);
return hasPerms(player, location, Flags.INTERACT_CONTAINER);
}
private boolean hasPerms(Player player, Location location, RoleSetting roleSetting) {
Area area = landsIntegration.getAreaByLoc(location);
private boolean hasPerms(Player player, Location location, RoleFlag roleFlag) {
Area area = this.landsIntegration.getArea(location);
if (area == null) {
return true;
}
return area.canSetting(player, roleSetting, false);
return area.getRole(player.getUniqueId()).hasFlag(roleFlag);
}
@Override
@ -48,6 +48,6 @@ public class LandsProtection extends Protection {
@Override
public boolean isEnabled() {
return landsIntegration != null;
return this.landsIntegration != null;
}
}

View File

@ -0,0 +1,70 @@
package com.songoda.core.hooks.protection;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class PlotSquaredProtection extends Protection {
public PlotSquaredProtection(Plugin plugin) {
super(plugin);
}
@Override
public String getName() {
return "PlotSquared";
}
@Override
public boolean isEnabled() {
return Bukkit.getPluginManager().isPluginEnabled("PlotSquared");
}
@Override
public boolean canPlace(Player player, Location location) {
return isPlayerAddedAtPlotLocation(player, location);
}
@Override
public boolean canBreak(Player player, Location location) {
return isPlayerAddedAtPlotLocation(player, location);
}
@Override
public boolean canInteract(Player player, Location location) {
return isPlayerAddedAtPlotLocation(player, location);
}
private boolean isPlayerAddedAtPlotLocation(Player player, Location location) {
PlotArea plotArea = getApplicablePlotArea(location);
if (plotArea == null) {
return true;
}
for (Plot p : plotArea.getPlots()) {
if (p.isAdded(player.getUniqueId())) {
return true;
}
}
return false;
}
private PlotArea getApplicablePlotArea(Location location) {
return PlotSquared.get()
.getPlotAreaManager()
.getApplicablePlotArea(getPlotSquaredLocation(location));
}
private com.plotsquared.core.location.Location getPlotSquaredLocation(Location location) {
return com.plotsquared.core.location.Location.at(
location.getWorld().getName(),
(int) location.getX(),
(int) location.getY(),
(int) location.getZ()
);
}
}

View File

@ -0,0 +1,9 @@
package com.songoda.core.http;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public interface HttpClient {
@NotNull HttpResponse get(String url) throws IOException;
}

View File

@ -0,0 +1,11 @@
package com.songoda.core.http;
import java.io.IOException;
public interface HttpResponse {
int getResponseCode() throws IOException;
byte[] getBody() throws IOException;
String getBodyAsString() throws IOException;
}

View File

@ -0,0 +1,54 @@
package com.songoda.core.http;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
public class HttpResponseImpl implements HttpResponse, AutoCloseable {
protected final HttpURLConnection connection;
protected byte[] body;
HttpResponseImpl(HttpURLConnection connection) throws IOException {
this.connection = connection;
this.connection.connect();
}
public int getResponseCode() throws IOException {
int statusCode = this.connection.getResponseCode();
if (statusCode == -1) {
throw new IOException("HTTP Status Code is -1");
}
return statusCode;
}
public byte[] getBody() throws IOException {
if (this.body == null) {
try (InputStream in = this.connection.getInputStream();
InputStream err = this.connection.getErrorStream()) {
if (err != null) {
this.body = IOUtils.toByteArray(err);
} else {
this.body = IOUtils.toByteArray(in);
}
}
}
return this.body;
}
public String getBodyAsString() throws IOException {
return new String(getBody(), StandardCharsets.UTF_8);
}
@Override
public void close() throws Exception {
this.connection.disconnect();
}
}

View File

@ -0,0 +1,31 @@
package com.songoda.core.http;
import com.songoda.core.SongodaCoreConstants;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class SimpleHttpClient implements HttpClient {
private static final String USER_AGENT = generateUserAgent();
public @NotNull HttpResponse get(String url) throws IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setInstanceFollowRedirects(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", USER_AGENT);
return new HttpResponseImpl(connection);
}
private static String generateUserAgent() {
String projectName = SongodaCoreConstants.getProjectName();
String version = SongodaCoreConstants.getCoreVersion();
String projectUrl = SongodaCoreConstants.getGitHubProjectUrl();
return projectName + "/" + version + " (+" + projectUrl + ")";
}
}

View File

@ -0,0 +1,15 @@
package com.songoda.core.http;
import java.io.IOException;
public class UnexpectedHttpStatusException extends IOException {
public final int responseCode;
public final String url;
public UnexpectedHttpStatusException(int responseCode, String url) {
super("Got HTTP Status Code " + responseCode + ": " + url);
this.responseCode = responseCode;
this.url = url;
}
}

View File

@ -1,9 +1,17 @@
package com.songoda.core.lootables.loot;
import com.bgsoftware.wildstacker.api.objects.StackedItem;
import com.songoda.core.SongodaCore;
import com.songoda.ultimatestacker.UltimateStacker;
import com.songoda.ultimatestacker.settings.Settings;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootTable;
import java.util.ArrayList;
import java.util.List;
@ -63,20 +71,74 @@ public class DropUtils {
}
private static void dropItems(List<ItemStack> items, EntityDeathEvent event) {
for (ItemStack item : items) {
event.getDrops().add(item);
if (SongodaCore.isRegistered("UltimateStacker")) {
List<StackedItem> stacks = new ArrayList<>();
int maxSize = Settings.MAX_STACK_ITEMS.getInt()-64;
for (ItemStack item : items) {
StackedItem stack = stacks.stream().filter(stackedItem -> stackedItem.getItem().getType() == item.getType()).findFirst().orElse(null);
if (stack == null) {
stacks.add(new StackedItem(item, item.getAmount()));
continue;
}
int newAmount = stack.getAmount() + item.getAmount();
while (newAmount > maxSize) {
newAmount -= maxSize;
stacks.add(new StackedItem(item, maxSize));
}
stack.setamount(newAmount);
}
Bukkit.getScheduler().runTask(UltimateStacker.getInstance(), () -> {
for (StackedItem stack : stacks) {
UltimateStacker.spawnStackedItem(stack.getItem(), stack.getAmount(), event.getEntity().getLocation());
}
});
return;
}
event.getDrops().addAll(items);
}
private static void runCommands(LivingEntity entity, List<String> commands) {
for (String command : commands) {
if (entity.getKiller() != null) {
command = command.replace("%player%", entity.getKiller().getName());
}
Bukkit.getScheduler().runTask(SongodaCore.getHijackedPlugin(), () -> {
for (String command : commands) {
if (entity.getKiller() != null) {
command = command.replace("%player%", entity.getKiller().getName()
.replace("%x%", String.valueOf((int) entity.getLocation().getX()))
.replace("%y%", String.valueOf((int) entity.getLocation().getY()))
.replace("%z%", String.valueOf((int) entity.getLocation().getZ())));
}
if (!command.contains("%player%")) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
if (!command.contains("%player%")) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
}
}
});
}
private static class StackedItem {
private final ItemStack item;
private int amount;
public StackedItem(ItemStack item, int amount) {
this.item = item;
this.amount = amount;
}
public Material getMaterial() {
return item.getType();
}
public ItemStack getItem() {
return item;
}
public int getAmount() {
return amount;
}
public void setamount(int amount) {
this.amount = amount;
}
}
}

View File

@ -4,9 +4,11 @@ import com.google.gson.annotations.SerializedName;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.utils.ItemUtils;
import com.songoda.core.utils.TextUtils;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import java.util.ArrayList;
import java.util.Arrays;
@ -149,6 +151,25 @@ public class Loot {
return null;
}
//Create enchantment book
if (item.getType().equals(Material.ENCHANTED_BOOK)) {
EnchantmentStorageMeta meta = (EnchantmentStorageMeta) item.getItemMeta();
for (Map.Entry<String, Integer> entry : this.enchants.entrySet()) {
if (entry.getValue() == null) continue;
//TODO add random enchants
// if (entry.getKey().equalsIgnoreCase("RANDOM")) {
// item = ItemUtils.applyRandomEnchants(item, entry.getValue());
//
// continue;
// }
meta.addStoredEnchant(Enchantment.getByName(entry.getKey()), entry.getValue(), true);
}
item.setItemMeta(meta);
return item;
}
Map<Enchantment, Integer> enchants = new HashMap<>();
for (Map.Entry<String, Integer> entry : this.enchants.entrySet()) {
if (entry.getValue() == null) continue;

View File

@ -12,10 +12,10 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -166,7 +166,7 @@ public class LootManager {
try {
Gson gson = new Gson();
JsonReader reader = new JsonReader(new FileReader(file.getPath()));
JsonReader reader = new JsonReader(Files.newBufferedReader(file.toPath()));
Lootable lootable = gson.fromJson(reader, Lootable.class);
@ -195,7 +195,7 @@ public class LootManager {
continue;
}
try (Writer writer = new FileWriter(file.getPath())) {
try (Writer writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
gson.toJson(lootable, writer);
}

View File

@ -1,5 +1,7 @@
package com.songoda.core.math;
import com.songoda.core.SongodaCoreConstants;
import java.util.HashMap;
import java.util.Map;
@ -7,7 +9,7 @@ public class MathUtils {
private static final Map<String, Double> cache = new HashMap<>();
public static double eval(String toParse) {
return eval(toParse, "SongodaCore Eval Engine");
return eval(toParse, SongodaCoreConstants.getProjectName() + " Eval Engine");
}
public static double eval(String toParse, String warningMessage) {

View File

@ -0,0 +1,22 @@
package com.songoda.core.nms;
import com.songoda.core.compatibility.ServerVersion;
public class Nms {
protected static NmsImplementations impl;
/**
* @return The implementations for the current server version
*/
public static NmsImplementations getImplementations() throws UnsupportedServerVersionException {
if (impl == null) {
try {
impl = (NmsImplementations) Class.forName("com.songoda.core.nms." + ServerVersion.getServerVersionString() + ".NmsImplementationsImpl").getConstructors()[0].newInstance();
} catch (ReflectiveOperationException ex) {
throw new UnsupportedServerVersionException(ex);
}
}
return impl;
}
}

View File

@ -3,172 +3,51 @@ package com.songoda.core.nms;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.entity.NMSPlayer;
import com.songoda.core.nms.nbt.NBTCore;
import com.songoda.core.nms.world.NmsWorldBorder;
import com.songoda.core.nms.world.WorldCore;
import org.bukkit.Bukkit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @deprecated Use {@link Nms} instead.
*/
@Deprecated
public class NmsManager {
private static final String serverPackagePath = Bukkit.getServer().getClass().getPackage().getName();
private static final String serverPackageVersion = serverPackagePath.substring(serverPackagePath.lastIndexOf('.') + 1);
private static final NMSPlayer player;
private static final AnvilCore anvil;
private static final NBTCore nbt;
private static final WorldCore world;
static {
switch (serverPackageVersion) {
case "v1_8_R1":
player = new com.songoda.core.nms.v1_8_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_8_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_8_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_8_R1.world.WorldCoreImpl();
break;
case "v1_8_R2":
player = new com.songoda.core.nms.v1_8_R2.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_8_R2.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_8_R2.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_8_R2.world.WorldCoreImpl();
break;
case "v1_8_R3":
player = new com.songoda.core.nms.v1_8_R3.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_8_R3.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_8_R3.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_8_R3.world.WorldCoreImpl();
break;
case "v1_9_R1":
player = new com.songoda.core.nms.v1_9_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_9_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_9_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_9_R1.world.WorldCoreImpl();
break;
case "v1_9_R2":
player = new com.songoda.core.nms.v1_9_R2.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_9_R2.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_9_R2.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_9_R2.world.WorldCoreImpl();
break;
case "v1_10_R1":
player = new com.songoda.core.nms.v1_10_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_10_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_10_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_10_R1.world.WorldCoreImpl();
break;
case "v1_11_R1":
player = new com.songoda.core.nms.v1_11_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_11_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_11_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_11_R1.world.WorldCoreImpl();
break;
case "v1_12_R1":
player = new com.songoda.core.nms.v1_12_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_12_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_12_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_12_R1.world.WorldCoreImpl();
break;
case "v1_13_R1":
player = new com.songoda.core.nms.v1_13_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_13_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_13_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_13_R1.world.WorldCoreImpl();
break;
case "v1_13_R2":
player = new com.songoda.core.nms.v1_13_R2.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_13_R2.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_13_R2.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_13_R2.world.WorldCoreImpl();
break;
case "v1_14_R1":
player = new com.songoda.core.nms.v1_14_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_14_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_14_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_14_R1.world.WorldCoreImpl();
break;
case "v1_15_R1":
player = new com.songoda.core.nms.v1_15_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_15_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_15_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_15_R1.world.WorldCoreImpl();
break;
case "v1_16_R1":
player = new com.songoda.core.nms.v1_16_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_16_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_16_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_16_R1.world.WorldCoreImpl();
break;
case "v1_16_R2":
player = new com.songoda.core.nms.v1_16_R2.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_16_R2.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_16_R2.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_16_R2.world.WorldCoreImpl();
break;
case "v1_16_R3":
player = new com.songoda.core.nms.v1_16_R3.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_16_R3.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_16_R3.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_16_R3.world.WorldCoreImpl();
break;
case "v1_17_R1":
player = new com.songoda.core.nms.v1_17_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_17_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_17_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_17_R1.world.WorldCoreImpl();
break;
case "v1_18_R1":
player = new com.songoda.core.nms.v1_18_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_18_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_18_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_18_R1.world.WorldCoreImpl();
break;
case "v1_18_R2":
player = new com.songoda.core.nms.v1_18_R2.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_18_R2.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_18_R2.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_18_R2.world.WorldCoreImpl();
break;
case "v1_19_R1":
player = new com.songoda.core.nms.v1_19_R1.entity.NMSPlayerImpl();
anvil = new com.songoda.core.nms.v1_19_R1.anvil.AnvilCore();
nbt = new com.songoda.core.nms.v1_19_R1.nbt.NBTCoreImpl();
world = new com.songoda.core.nms.v1_19_R1.world.WorldCoreImpl();
break;
default:
Logger.getLogger(NmsManager.class.getName()).log(Level.SEVERE, "Failed to load NMS for this server version: version {0} not found", serverPackageVersion);
player = null;
anvil = null;
nbt = null;
world = null;
break;
}
}
@Deprecated
public static NMSPlayer getPlayer() {
return player;
return Nms.getImplementations().getPlayer();
}
@Deprecated
public static AnvilCore getAnvil() {
return anvil;
return Nms.getImplementations().getAnvil();
}
@Deprecated
public static boolean hasAnvil() {
return anvil != null;
return getAnvil() != null;
}
@Deprecated
public static NBTCore getNbt() {
return nbt;
return Nms.getImplementations().getNbt();
}
@Deprecated
public static boolean hasNbt() {
return nbt != null;
return getNbt() != null;
}
@Deprecated
public static WorldCore getWorld() {
return world;
return Nms.getImplementations().getWorld();
}
@Deprecated
public static boolean hasWorld() {
return world != null;
return getWorld() != null;
}
@Deprecated
public static NmsWorldBorder getWorldBorder() {
return Nms.getImplementations().getWorldBorder();
}
}

View File

@ -0,0 +1,17 @@
package com.songoda.core.nms;
import com.songoda.core.compatibility.ServerVersion;
public class UnsupportedServerVersionException extends RuntimeException {
public UnsupportedServerVersionException() {
this(null);
}
public UnsupportedServerVersionException(Throwable cause) {
this("Your sever version (" + ServerVersion.getServerVersionString() + "; " + ServerVersion.getServerVersion().name() + ") is not fully supported", null);
}
protected UnsupportedServerVersionException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -19,6 +19,10 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @deprecated This class will be removed in the future and replaced with a more maintainable system.
*/
@Deprecated
public class BlockUtils {
protected static final Set<Material> DOORS;
protected static final Set<Material> PRESSURE_PLATES;
@ -337,7 +341,11 @@ public class BlockUtils {
* Manually trigger the updateAdjacentComparators method for containers
*
* @param loc The Location of the container
*
* @deprecated Use {@link com.songoda.core.nms.world.WorldCore#updateAdjacentComparators(Block)}
* via {@link com.songoda.core.nms.Nms#getImplementations()} instead.
*/
@Deprecated
public static void updateAdjacentComparators(Location loc) {
if (loc == null || loc.getWorld() == null) {
return;
@ -398,7 +406,11 @@ public class BlockUtils {
* <p>
* The chunk must be loaded and players must relog if they have the
* chunk loaded in order to use this method.
*
* @deprecated Use {@link com.songoda.core.nms.world.SWorld#setBlockFast(int, int, int, Material)}
* via {@link com.songoda.core.nms.Nms#getImplementations()} instead.
*/
@Deprecated
public static void setBlockFast(World world, int x, int y, int z, Material material, byte data) {
try {
// Cache reflection
@ -443,6 +455,11 @@ public class BlockUtils {
}
}
/**
* @deprecated Use {@link com.songoda.core.nms.world.SWorld#setBlockFast(int, int, int, Material)}
* via {@link com.songoda.core.nms.Nms#getImplementations()} instead.
*/
@Deprecated
public static void setBlockFast(World world, int x, int y, int z, CompatibleMaterial material, byte data) {
setBlockFast(world, x, y, z, material.getBlockMaterial(), data);
}
@ -468,8 +485,7 @@ public class BlockUtils {
return false;
}
return block.getData() >= (mat == CompatibleMaterial.BEETROOTS
|| mat == CompatibleMaterial.NETHER_WART ? 3 : 7);
return block.getData() >= (mat == CompatibleMaterial.BEETROOTS || mat == CompatibleMaterial.NETHER_WART ? 3 : 7);
}
/**
@ -518,8 +534,7 @@ public class BlockUtils {
return -1;
}
return (mat == CompatibleMaterial.BEETROOTS
|| mat == CompatibleMaterial.NETHER_WART ? 3 : 7);
return (mat == CompatibleMaterial.BEETROOTS || mat == CompatibleMaterial.NETHER_WART ? 3 : 7);
}
/**

View File

@ -22,6 +22,10 @@ import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @deprecated This class will be removed in the future and replaced with a more maintainable system.
*/
@Deprecated
public class BlockUtilsModern {
protected static void _updatePressurePlateModern(Block plate, int power) {
BlockData blockData = plate.getBlockData();

View File

@ -35,6 +35,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
@ -82,6 +83,7 @@ public class ItemUtils {
}
private static Method methodAsBukkitCopy, methodAsNMSCopy, methodA;
private static Object randomInstance;
static {
try {
@ -90,17 +92,20 @@ public class ItemUtils {
Class<?> clazzCraftItemStack = ClassMapping.CRAFT_ITEM_STACK.getClazz();
methodAsBukkitCopy = clazzCraftItemStack.getMethod("asBukkitCopy", clazzItemStack);
methodAsNMSCopy = clazzCraftItemStack.getMethod("asNMSCopy", ItemStack.class);
methodAsNMSCopy = MethodMapping.CB_ITEM_STACK__AS_NMS_COPY.getMethod(clazzCraftItemStack);
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_19)) {
Class<?> clazzRandomSource = ClassMapping.RANDOM_SOURCE.getClazz();
methodA = clazzEnchantmentManager.getMethod("a", clazzRandomSource.getMethod("c").getReturnType(), clazzItemStack, int.class, boolean.class);
}else if (ServerVersion.isServerVersion(ServerVersion.V1_8)) {
randomInstance = ClassMapping.SINGLE_THREADED_RANDOM_SOURCE.getClazz().getConstructor(long.class).newInstance(ThreadLocalRandom.current().nextLong());
} else if (ServerVersion.isServerVersion(ServerVersion.V1_8)) {
methodA = clazzEnchantmentManager.getMethod("a", Random.class, clazzItemStack, int.class);
randomInstance = new Random();
} else {
methodA = clazzEnchantmentManager.getMethod("a", Random.class, clazzItemStack, int.class, boolean.class);
randomInstance = new Random();
}
} catch (NoSuchMethodException ex) {
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
@ -109,10 +114,12 @@ public class ItemUtils {
try {
Object nmsItemStack = methodAsNMSCopy.invoke(null, item);
if (ServerVersion.isServerVersion(ServerVersion.V1_8)) {
nmsItemStack = methodA.invoke(null, new Random(), nmsItemStack, level);
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_19)) {
nmsItemStack = methodA.invoke(null, randomInstance, nmsItemStack, level, false);
} else if (ServerVersion.isServerVersion(ServerVersion.V1_8)) {
nmsItemStack = methodA.invoke(null, randomInstance, nmsItemStack, level);
} else {
nmsItemStack = methodA.invoke(null, new Random(), nmsItemStack, level, false);
nmsItemStack = methodA.invoke(null, randomInstance, nmsItemStack, level, false);
}
item = (ItemStack) methodAsBukkitCopy.invoke(null, nmsItemStack);

View File

@ -0,0 +1,111 @@
package com.songoda.core.utils;
import org.bukkit.Bukkit;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import java.util.UUID;
public class SongodaAuth {
public static boolean isAuthorized(boolean allowOffline) {
String productId = "%%__PLUGIN__%%";
if (isPluginSelfCompiled(productId)) {
return true;
}
UUID serverUuid = getUUID();
try {
URL url = new URL("https://marketplace.songoda.com/api/v2/products/license/validate");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);
String requestBodyJson = "{\"product_id\":" + productId + ",\"license\":\"" + serverUuid + "\",\"user_id\":\"%%__USER__%%\"}";
try (OutputStream os = con.getOutputStream()) {
byte[] requestBody = requestBodyJson.getBytes(StandardCharsets.UTF_8);
os.write(requestBody, 0, requestBody.length);
}
JSONObject jsonResponse = readHttpResponseJson(con);
if (jsonResponse.containsKey("error")) {
Bukkit.getLogger().warning("Error validating license: " + jsonResponse.get("error"));
return false;
}
return (boolean) jsonResponse.get("valid");
} catch (Exception ex) {
return allowOffline;
}
}
public static UUID getUUID() {
File serverProperties = new File("./server.properties");
try {
Properties prop = new Properties();
prop.load(new FileReader(serverProperties));
String uuid = prop.getProperty("uuid");
if (uuid != null && !uuid.isEmpty()) {
return UUID.fromString(uuid);
}
UUID newUUID = UUID.randomUUID();
prop.setProperty("uuid", newUUID.toString());
prop.store(new FileWriter(serverProperties), null);
return newUUID;
} catch (Exception ex) {
throw new RuntimeException("Could not determine UUID for server", ex);
}
}
public static String getIP() {
try {
URL url = new URL("https://marketplace.songoda.com/api/v2/products/license/ip");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
JSONObject jsonResponse = readHttpResponseJson(con);
return jsonResponse.get("ip").toString();
} catch (Exception ex) {
throw new RuntimeException("Could not fetch IP address", ex);
}
}
private static JSONObject readHttpResponseJson(HttpURLConnection con) throws IOException, ParseException {
try (BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
return (JSONObject) new JSONParser().parse(response.toString());
}
}
private static boolean isPluginSelfCompiled(String productId) {
try {
Integer.parseInt(productId);
return false;
} catch (NumberFormatException ignore) {
}
return true;
}
}

View File

@ -3,7 +3,7 @@ package com.songoda.core.world;
import com.songoda.core.compatibility.CompatibleHand;
import com.songoda.core.compatibility.CompatibleSound;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.Nms;
import org.bukkit.Bukkit;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
@ -18,12 +18,12 @@ public class SItemStack {
public SItemStack(ItemStack item) {
this.item = item;
this.sItem = NmsManager.getWorld().getItemStack(item);
this.sItem = Nms.getImplementations().getWorld().getItemStack(item);
}
public SItemStack(CompatibleHand hand, Player player) {
this.item = hand.getItem(player);
this.sItem = NmsManager.getWorld().getItemStack(item);
this.sItem = Nms.getImplementations().getWorld().getItemStack(item);
}
public ItemStack addDamage(Player player, int damage) {
@ -49,7 +49,7 @@ public class SItemStack {
int durability;
if (ServerVersion.isServerVersionBelow(ServerVersion.V1_11)
? NmsManager.getNbt().of(item).has("Unbreakable")
? Nms.getImplementations().getNbt().of(item).has("Unbreakable")
: item.getItemMeta().isUnbreakable()) {
return item;
} else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {

View File

@ -2,7 +2,7 @@ package com.songoda.core.world;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.hooks.EntityStackerManager;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.Nms;
import com.songoda.core.nms.world.SpawnedEntity;
import com.songoda.core.utils.EntityUtils;
import org.bukkit.Location;
@ -20,7 +20,7 @@ public class SSpawner {
public SSpawner(Location location) {
this.location = location;
this.sSpawner = NmsManager.getWorld().getSpawner(location);
this.sSpawner = Nms.getImplementations().getWorld().getSpawner(location);
}
public SSpawner(CreatureSpawner spawner) {

View File

@ -1,7 +1,7 @@
package com.songoda.core.world;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.Nms;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
@ -15,7 +15,7 @@ public class SWorld {
public SWorld(World world) {
this.world = world;
this.sWorld = NmsManager.getWorld().getWorld(world);
this.sWorld = Nms.getImplementations().getWorld().getWorld(world);
}
public Entity[] getEntitiesFromChunk(int x, int z) {

View File

@ -3,7 +3,7 @@ package com.songoda.core.world;
import com.songoda.core.compatibility.ClassMapping;
import com.songoda.core.compatibility.MethodMapping;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.Nms;
import com.songoda.core.utils.NMSUtils;
import org.bukkit.Location;
import org.bukkit.entity.Player;
@ -12,6 +12,10 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @deprecated Use {@link com.songoda.core.nms.world.NmsWorldBorder} via {@link Nms#getImplementations()} instead.
*/
@Deprecated
public class SWorldBorder {
private static Class<?> packetPlayOutWorldBorderEnumClass;
private static Class<?> worldBorderClass;
@ -81,18 +85,22 @@ public class SWorldBorder {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17)) {
Object packet = clientboundInitializeBorderPacketConstructor.newInstance(worldBorder);
NmsManager.getPlayer().sendPacket(player, packet);
Nms.getImplementations().getPlayer().sendPacket(player, packet);
} else {
@SuppressWarnings({"unchecked", "rawtypes"})
Object packet = packetPlayOutWorldBorderConstructor.newInstance(worldBorder,
Enum.valueOf((Class<? extends Enum>) packetPlayOutWorldBorderEnumClass, "INITIALIZE"));
NmsManager.getPlayer().sendPacket(player, packet);
Nms.getImplementations().getPlayer().sendPacket(player, packet);
}
} catch (InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException ex) {
ex.printStackTrace();
}
}
/**
* @deprecated Use {@link com.songoda.core.nms.world.NmsWorldBorder.BorderColor} instead.
*/
@Deprecated
public enum Color {
Blue, Green, Red
}

View File

@ -0,0 +1,36 @@
package com.songoda.core;
import org.junit.jupiter.api.Test;
import org.opentest4j.TestSkippedException;
import java.util.Objects;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class SongodaCoreConstantsTest {
// Pattern is from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
private static final Pattern VERSION_PATTERN = Pattern.compile("^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
@Test
void getCoreVersion() {
if (!Objects.equals(System.getenv("TESTS_RUN_WITH_MAVEN"), "true")) {
throw new TestSkippedException("Skipping test because it requires the TESTS_RUN_WITH_MAVEN environment variable to be set to true");
}
String coreVersion = SongodaCoreConstants.getCoreVersion();
assertTrue(VERSION_PATTERN.matcher(coreVersion).matches(), "Version string is not a valid semver string: " + coreVersion);
}
@Test
void getProjectName() {
assertFalse(SongodaCoreConstants.getProjectName().isEmpty());
}
@Test
void getGitHubProjectUrl() {
assertFalse(SongodaCoreConstants.getGitHubProjectUrl().isEmpty());
}
}

View File

@ -1,86 +0,0 @@
package com.songoda.core.compatibility.material;
import be.seeseemelk.mockbukkit.MockBukkit;
import com.songoda.core.compatibility.CompatibleMaterial;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
class CompatibleMaterialTest {
@BeforeEach
void setUp() {
MockBukkit.mock();
}
@AfterEach
void tearDown() {
MockBukkit.unmock();
}
@Test
void getMaterialForNull() {
assertNull(CompatibleMaterial.getMaterial((Material) null));
assertNull(CompatibleMaterial.getMaterial((ItemStack) null));
}
@Test
void getMaterialForAllBukkitMaterials() {
Map<CompatibleMaterial, Material> returnedMaterials = new HashMap<>(Material.values().length);
for (Material bukkitMaterial : Material.values()) {
CompatibleMaterial compatibleMaterial = CompatibleMaterial.getMaterial(bukkitMaterial);
if (bukkitMaterial.name().startsWith("LEGACY_")) {
assertNull(compatibleMaterial);
continue;
}
assertNotNull(compatibleMaterial, () -> "Could not get an CompatibleMaterial for Material." + bukkitMaterial.name());
assertEquals(bukkitMaterial, compatibleMaterial.getMaterial());
assertEquals(compatibleMaterial, CompatibleMaterial.getMaterial(bukkitMaterial.name()));
assertFalse(returnedMaterials.containsKey(compatibleMaterial),
() -> String.format("Assertion failed when converting Material.%s to CompatibleMaterial.%s: " +
"CompatibleMaterial.%1$s has already been returned for Material.%3$s previously",
bukkitMaterial.name(),
compatibleMaterial.name(),
returnedMaterials.get(compatibleMaterial).name()
));
assertEquals(bukkitMaterial.isAir(), compatibleMaterial.isAir(), getMaterialPropertyAssertionError(compatibleMaterial, "Air"));
assertEquals(bukkitMaterial.isBlock(), compatibleMaterial.isBlock(), getMaterialPropertyAssertionError(compatibleMaterial, "Block"));
assertEquals(bukkitMaterial.isBurnable(), compatibleMaterial.isBurnable(), getMaterialPropertyAssertionError(compatibleMaterial, "Burnable"));
assertEquals(bukkitMaterial.isEdible(), compatibleMaterial.isEdible(), getMaterialPropertyAssertionError(compatibleMaterial, "Edible"));
assertEquals(bukkitMaterial.isFlammable(), compatibleMaterial.isFlammable(), getMaterialPropertyAssertionError(compatibleMaterial, "Flammable"));
assertEquals(bukkitMaterial.isFuel(), compatibleMaterial.isFuel(), getMaterialPropertyAssertionError(compatibleMaterial, "Fuel"));
assertEquals(bukkitMaterial.isInteractable(), compatibleMaterial.isInteractable(), getMaterialPropertyAssertionError(compatibleMaterial, "Interactable"));
assertEquals(bukkitMaterial.isItem(), compatibleMaterial.isItem(), getMaterialPropertyAssertionError(compatibleMaterial, "Item"));
assertEquals(bukkitMaterial.isOccluding(), compatibleMaterial.isOccluding(), getMaterialPropertyAssertionError(compatibleMaterial, "Occluding"));
assertEquals(bukkitMaterial.isSolid(), compatibleMaterial.isSolid(), getMaterialPropertyAssertionError(compatibleMaterial, "Solid"));
assertEquals(bukkitMaterial.isTransparent(), compatibleMaterial.isTransparent(), getMaterialPropertyAssertionError(compatibleMaterial, "Transparent"));
assertFalse(compatibleMaterial.usesCompatibility());
assertFalse(compatibleMaterial.usesData());
assertEquals(-1, compatibleMaterial.getData());
ItemStack compatibleItem = compatibleMaterial.getItem();
assertEquals(bukkitMaterial, compatibleItem.getType());
assertEquals(compatibleMaterial, CompatibleMaterial.getMaterial(compatibleItem));
returnedMaterials.put(compatibleMaterial, bukkitMaterial);
}
}
private Supplier<String> getMaterialPropertyAssertionError(CompatibleMaterial compatibleMaterial, String propertyName) {
return () -> String.format("Expected CompatibleMaterial.%s to be '%s'", compatibleMaterial.name(), propertyName);
}
}

View File

@ -0,0 +1,22 @@
package com.songoda.core.http;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedList;
import java.util.List;
public class MockHttpClient implements HttpClient {
public HttpResponse returnValue;
public List<String> callsOnGet = new LinkedList<>();
public MockHttpClient(HttpResponse returnValue) {
this.returnValue = returnValue;
}
@Override
public @NotNull HttpResponse get(String url) {
this.callsOnGet.add(url);
return this.returnValue;
}
}

View File

@ -0,0 +1,25 @@
package com.songoda.core.http;
import java.nio.charset.StandardCharsets;
public class MockHttpResponse implements HttpResponse {
public int responseCode;
public byte[] body;
public MockHttpResponse(int responseCode, byte[] body) {
this.responseCode = responseCode;
this.body = body;
}
public int getResponseCode() {
return this.responseCode;
}
public byte[] getBody() {
return this.body;
}
public String getBodyAsString() {
return new String(getBody(), StandardCharsets.UTF_8);
}
}

View File

@ -1,127 +0,0 @@
package com.songoda.core.input;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.MockPlugin;
import be.seeseemelk.mockbukkit.ServerMock;
import be.seeseemelk.mockbukkit.entity.PlayerMock;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Disabled("BukkitMock seems to cause some troubles here, skipping for now")
class ChatPromptTest {
private final String inputMsg = "&eInput-Message";
private ServerMock server;
private MockPlugin plugin;
private PlayerMock player;
@BeforeEach
void setUp() {
this.server = MockBukkit.mock();
this.plugin = MockBukkit.createMockPlugin();
this.player = this.server.addPlayer();
}
@AfterEach
void tearDown() {
MockBukkit.unmock();
}
@Test
void showPrompt() throws InterruptedException {
List<String> chatInputs = new ArrayList<>(1);
ChatPrompt.showPrompt(this.plugin, this.player, event -> {
assertEquals(this.player, event.getPlayer());
chatInputs.add(event.getMessage());
});
this.player.chat(this.inputMsg);
Thread.sleep(1000);
// this.server.getScheduler().waitAsyncTasksFinished() // does not wait for async events
String playerReceivedMsg = this.player.nextMessage();
assertNotNull(playerReceivedMsg);
assertTrue(playerReceivedMsg.endsWith(this.inputMsg));
assertEquals(1, chatInputs.size());
assertEquals(this.inputMsg, chatInputs.get(0));
}
/* FIXME: Something is still running in the background and prevents the test from finishing */
@Disabled("Scheduling mock seems bugged, skipping for now")
@Test
void showPromptWithTimeout() {
AtomicBoolean calledOnClose = new AtomicBoolean(false);
ChatPrompt.showPrompt(this.plugin, this.player, event -> {
})
.setOnClose(() -> calledOnClose.set(true))
.setTimeOut(this.player, 40);
this.server.getScheduler().performTicks(40);
String playerReceivedMsg = this.player.nextMessage();
assertNotNull(playerReceivedMsg);
assertTrue(playerReceivedMsg.contains("timed out"));
this.server.getScheduler().performOneTick();
assertTrue(calledOnClose.get());
}
@Test
void cancelPrompt() {
AtomicBoolean calledOnCancel = new AtomicBoolean(false);
AtomicBoolean calledHandler = new AtomicBoolean(false);
ChatPrompt prompt = ChatPrompt.showPrompt(plugin, player, (event) -> calledHandler.set(true));
prompt.setOnCancel(() -> calledOnCancel.set(true));
this.server.dispatchCommand(player, "cancel");
// this.player.chat("/cancel");
// Thread.sleep(1000);
// this.server.getScheduler().waitAsyncTasksFinished() // does not wait for async events
System.out.println(this.player.nextMessage());
// assertTrue(player.nextMessage().endsWith("/cancel"));
assertTrue(calledOnCancel.get());
assertFalse(calledHandler.get());
}
@Test
void isRegistered() {
assertFalse(ChatPrompt.isRegistered(this.player));
ChatPrompt.showPrompt(this.plugin, this.player, (event) -> {
});
assertTrue(ChatPrompt.isRegistered(this.player));
}
@Test
void unregister() {
assertFalse(ChatPrompt.unregister(this.player));
ChatPrompt.showPrompt(this.plugin, this.player, (event) -> {
});
assertTrue(ChatPrompt.unregister(this.player));
assertFalse(ChatPrompt.unregister(this.player));
}
}

View File

@ -2,16 +2,19 @@ package com.songoda.core.math;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;
class MathUtilsTest {
private final String warningMessage = "MathTest";
private final String warningMessageExpectedStart = warningMessage + " ";
private final String warningMessageExpectedStart = this.warningMessage + " ";
@Test
void eval() {
assertEquals(0, MathUtils.eval("0"));
assertEquals(10, MathUtils.eval("10"));
assertEquals(0.0, MathUtils.eval("0.0"));
assertEquals(10.5, MathUtils.eval("10.5"));
assertEquals(10.5 + 4, MathUtils.eval("10.5 + 4"));
assertEquals(10.5 - 5, MathUtils.eval("10.5 - 5"));
assertEquals(10 * 4, MathUtils.eval("10 * 4"));
@ -33,28 +36,28 @@ class MathUtilsTest {
@Test
void evalWithCommaAsDecimalSeparator() {
Exception ex = assertThrowsExactly(RuntimeException.class, () -> MathUtils.eval("1,0", warningMessage));
Exception ex = assertThrowsExactly(RuntimeException.class, () -> MathUtils.eval("1,0", this.warningMessage));
assertTrue(ex.getMessage().startsWith(warningMessageExpectedStart),
() -> "'" + ex.getMessage() + "' does not start with '" + warningMessageExpectedStart + "'");
assertTrue(ex.getMessage().startsWith(this.warningMessageExpectedStart),
() -> "'" + ex.getMessage() + "' does not start with '" + this.warningMessageExpectedStart + "'");
assertTrue(ex.getMessage().contains("Unexpected: "));
}
@Test
void evalWithUnsupportedSyntax() {
Exception ex = assertThrowsExactly(RuntimeException.class, () -> MathUtils.eval("!2", warningMessage));
Exception ex = assertThrowsExactly(RuntimeException.class, () -> MathUtils.eval("!2", this.warningMessage));
assertTrue(ex.getMessage().startsWith(warningMessageExpectedStart),
() -> "'" + ex.getMessage() + "' does not start with '" + warningMessageExpectedStart + "'");
assertTrue(ex.getMessage().startsWith(this.warningMessageExpectedStart),
() -> "'" + ex.getMessage() + "' does not start with '" + this.warningMessageExpectedStart + "'");
assertTrue(ex.getMessage().contains("Unexpected: "));
}
@Test
void evalWithUnsupportedFunction() {
Exception ex = assertThrowsExactly(RuntimeException.class, () -> MathUtils.eval("acos(90)", warningMessage));
Exception ex = assertThrowsExactly(RuntimeException.class, () -> MathUtils.eval("acos(90)", this.warningMessage));
assertTrue(ex.getMessage().startsWith(warningMessageExpectedStart),
() -> "'" + ex.getMessage() + "' does not start with '" + warningMessageExpectedStart + "'");
assertTrue(ex.getMessage().startsWith(this.warningMessageExpectedStart),
() -> "'" + ex.getMessage() + "' does not start with '" + this.warningMessageExpectedStart + "'");
assertTrue(ex.getMessage().contains("Unknown function: "));
}
}

View File

@ -1,9 +1,10 @@
package com.songoda.core.utils;
import be.seeseemelk.mockbukkit.WorldMock;
import org.bukkit.Location;
import org.bukkit.World;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -13,12 +14,20 @@ class LocationUtilsTest {
void isLocationMatching() {
assertTrue(LocationUtils.isLocationMatching(
new Location(null, 10, 20, 30),
new Location(new WorldMock(), 10.25, 20.5, 30.75)
new Location(Mockito.mock(World.class), 10.25, 20.5, 30.75)
));
assertTrue(LocationUtils.isLocationMatching(
new Location(null, 10, 20, 30),
new Location(null, 10.25, 20.5, 30.75)
));
assertFalse(LocationUtils.isLocationMatching(
new Location(null, 10, 20, 30),
new Location(new WorldMock(), -10.25, 20.5, 30.75)
new Location(Mockito.mock(World.class), -10.25, 20.5, 30.75)
));
assertFalse(LocationUtils.isLocationMatching(
new Location(Mockito.mock(World.class), 10, 20, 30),
new Location(null, -10.25, 20.5, 30.75)
));
}

View File

@ -1,134 +1,143 @@
package com.songoda.core.utils;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import be.seeseemelk.mockbukkit.entity.PlayerMock;
import org.bukkit.Material;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.bukkit.inventory.PlayerInventory;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;
class PlayerUtilsTest {
private ServerMock server;
@Test
void sendMessages_Array() {
Player player = Mockito.mock(Player.class);
PlayerUtils.sendMessages(player, "First message", "Second message");
@BeforeEach
void setUp() {
this.server = MockBukkit.mock();
}
@AfterEach
void tearDown() {
MockBukkit.unmock();
this.server = null;
InOrder playerInOrder = Mockito.inOrder(player);
playerInOrder.verify(player).sendMessage("First message");
playerInOrder.verify(player).sendMessage("Second message");
playerInOrder.verify(player, Mockito.never()).sendMessage(Mockito.anyString());
}
@Test
void sendMessages() {
String[] messages = new String[] {"First message", "Second message"};
void sendMessages_List() {
Player player = Mockito.mock(Player.class);
PlayerUtils.sendMessages(player, Arrays.asList("First message", "Second message"));
PlayerMock player = this.server.addPlayer();
PlayerUtils.sendMessages(player, messages);
PlayerUtils.sendMessages(player, Arrays.asList(messages));
for (int i = 0; i < 2; ++i) {
assertEquals(messages[0], player.nextMessage());
assertEquals(messages[1], player.nextMessage());
}
assertNull(player.nextMessage());
InOrder playerInOrder = Mockito.inOrder(player);
playerInOrder.verify(player).sendMessage("First message");
playerInOrder.verify(player).sendMessage("Second message");
playerInOrder.verify(player, Mockito.never()).sendMessage(Mockito.anyString());
}
@Disabled("Player#hidePlayer can currently not be mocked")
@Test
void getVisiblePlayerNames() {
PlayerMock player = this.server.addPlayer("BasePlayer");
PlayerMock visiblePlayer = this.server.addPlayer("VisiblePlayer");
PlayerMock hiddenPlayer = this.server.addPlayer("HiddenPlayer");
Player player = createMockPlayer("BasePlayer");
Player visiblePlayer = createMockPlayer("VisiblePlayer");
Player hiddenPlayer = createMockPlayer("HiddenPlayer");
player.hidePlayer(MockBukkit.createMockPlugin(), hiddenPlayer);
List<String> result;
try (MockedStatic<Bukkit> server = Mockito.mockStatic(Bukkit.class)) {
server.when(Bukkit::getOnlinePlayers).thenReturn(Arrays.asList(player, visiblePlayer, hiddenPlayer));
List<String> result = PlayerUtils.getVisiblePlayerNames(player, null);
assertTrue(result.contains(visiblePlayer.getName()));
assertFalse(result.contains(hiddenPlayer.getName()));
assertFalse(result.contains(player.getName()));
Mockito.when(player.canSee(hiddenPlayer)).thenReturn(false);
Mockito.when(player.canSee(visiblePlayer)).thenReturn(true);
assertEquals(0, PlayerUtils.getVisiblePlayerNames(player, "_").size());
assertEquals(0, PlayerUtils.getVisiblePlayerNames(player, "_").size());
result = PlayerUtils.getVisiblePlayerNames(player, null);
}
assertTrue(result.contains("VisiblePlayer"));
assertEquals(1, result.size());
}
@Disabled("Player#hidePlayer can currently not be mocked")
@Test
void getVisiblePlayerDisplayNames() {
PlayerMock player = this.server.addPlayer("BasePlayer");
PlayerMock visiblePlayer = this.server.addPlayer("VisiblePlayer");
PlayerMock hiddenPlayer = this.server.addPlayer("HiddenPlayer");
Player player = createMockPlayer("BasePlayer");
Player visiblePlayer = createMockPlayer("VisiblePlayer", "VisibleDisplayName");
Player hiddenPlayer = createMockPlayer("HiddenPlayer");
player.setDisplayName("Base");
visiblePlayer.setDisplayName("Visible");
hiddenPlayer.setDisplayName("Hidden");
List<String> result;
try (MockedStatic<Bukkit> server = Mockito.mockStatic(Bukkit.class)) {
server.when(Bukkit::getOnlinePlayers).thenReturn(Arrays.asList(player, visiblePlayer, hiddenPlayer));
player.hidePlayer(MockBukkit.createMockPlugin(), hiddenPlayer);
Mockito.when(player.canSee(hiddenPlayer)).thenReturn(false);
Mockito.when(player.canSee(visiblePlayer)).thenReturn(true);
List<String> result = PlayerUtils.getVisiblePlayerDisplayNames(player, null);
assertTrue(result.contains(visiblePlayer.getDisplayName()));
assertFalse(result.contains(hiddenPlayer.getDisplayName()));
assertFalse(result.contains(player.getDisplayName()));
assertEquals(0, PlayerUtils.getVisiblePlayerDisplayNames(player, "A").size());
assertEquals(0, PlayerUtils.getVisiblePlayerDisplayNames(player, "_").size());
result = PlayerUtils.getVisiblePlayerDisplayNames(player, null);
}
assertTrue(result.contains("VisibleDisplayName"));
assertEquals(1, result.size());
}
@Disabled("Player#hidePlayer can currently not be mocked")
@Test
void getVisiblePlayers() {
PlayerMock player = this.server.addPlayer("BasePlayer");
PlayerMock visiblePlayer = this.server.addPlayer("VisiblePlayer");
PlayerMock hiddenPlayer = this.server.addPlayer("HiddenPlayer");
Player player = createMockPlayer("BasePlayer");
Player visiblePlayer = createMockPlayer("VisiblePlayer");
Player hiddenPlayer = createMockPlayer("HiddenPlayer");
player.hidePlayer(MockBukkit.createMockPlugin(), hiddenPlayer);
Mockito.when(player.canSee(hiddenPlayer)).thenReturn(false);
Mockito.when(player.canSee(visiblePlayer)).thenReturn(true);
List<Player> result;
try (MockedStatic<Bukkit> server = Mockito.mockStatic(Bukkit.class)) {
server.when(Bukkit::getOnlinePlayers).thenReturn(Arrays.asList(player, visiblePlayer, hiddenPlayer));
assertEquals(0, PlayerUtils.getVisiblePlayers(player, "_").size());
result = PlayerUtils.getVisiblePlayers(player, null);
}
List<Player> result = PlayerUtils.getVisiblePlayers(player, null);
assertTrue(result.contains(visiblePlayer));
assertFalse(result.contains(hiddenPlayer));
assertFalse(result.contains(player));
assertEquals(0, PlayerUtils.getVisiblePlayers(player, "_").size());
assertEquals(1, result.size());
}
@Test
void getAllPlayers() {
PlayerMock basePlayer = this.server.addPlayer("BasePlayer");
this.server.addPlayer("Player_1");
this.server.addPlayer("Player_2");
this.server.addPlayer("Player3");
Player basePlayer = createMockPlayer("BasePlayer");
Player player1 = createMockPlayer("Player_1");
Player player2 = createMockPlayer("Player_2");
Player player3 = createMockPlayer("Player3");
List<String> result = PlayerUtils.getAllPlayers(basePlayer, "");
assertEquals(3, result.size());
assertFalse(result.contains(basePlayer.getName()));
try (MockedStatic<Bukkit> server = Mockito.mockStatic(Bukkit.class)) {
server.when(Bukkit::getOnlinePlayers).thenReturn(Arrays.asList(basePlayer, player1, player2, player3));
assertTrue(PlayerUtils.getAllPlayers(basePlayer, "_").isEmpty());
assertEquals(0, PlayerUtils.getAllPlayers(basePlayer, "Player_").size());
assertEquals(0, PlayerUtils.getVisiblePlayers(basePlayer, "_").size());
List<String> result = PlayerUtils.getAllPlayers(basePlayer, "");
assertFalse(result.contains(basePlayer.getName()));
assertEquals(3, result.size());
assertEquals(0, PlayerUtils.getAllPlayers(basePlayer, "_").size());
assertEquals(0, PlayerUtils.getAllPlayers(basePlayer, "Player_").size());
}
}
@Disabled("Disabled for now as the implementations seems to be faulty")
@Test
void getAllPlayersDisplay() {
PlayerMock basePlayer = this.server.addPlayer("BasePlayer");
this.server.addPlayer("Player_1");
this.server.addPlayer("Player_2");
this.server.addPlayer("Player3");
Player basePlayer = createMockPlayer("BasePlayer");
createMockPlayer("Player_1");
createMockPlayer("Player_2");
createMockPlayer("Player3");
List<String> result = PlayerUtils.getAllPlayersDisplay(basePlayer, "");
assertEquals(3, result.size());
@ -141,13 +150,9 @@ class PlayerUtilsTest {
@Disabled("Disabled for now as the implementations seems to be faulty")
@Test
void findPlayer() {
Player p3 = this.server.addPlayer("Player");
Player p1 = this.server.addPlayer("Player_1");
Player p2 = this.server.addPlayer("_Player_2");
p1.setDisplayName("p1");
p2.setDisplayName("p2");
p3.setDisplayName("p3");
Player p3 = createMockPlayer("Player", "p3");
Player p1 = createMockPlayer("Player_1", "p1");
Player p2 = createMockPlayer("_Player_2", "p2");
assertEquals(p1, PlayerUtils.findPlayer("Player_"));
assertEquals(p2, PlayerUtils.findPlayer("_Play"));
@ -160,73 +165,185 @@ class PlayerUtilsTest {
}
@Test
void getRandomPlayer() {
assertNull(PlayerUtils.getRandomPlayer());
for (int i = 0; i < 10; ++i) {
this.server.addPlayer(String.valueOf(i));
void getRandomPlayer_NoneOnline() {
try (MockedStatic<Bukkit> server = Mockito.mockStatic(Bukkit.class)) {
server.when(Bukkit::getOnlinePlayers).thenReturn(Collections.emptyList());
assertNull(PlayerUtils.getRandomPlayer());
}
}
Set<Player> returnedPlayers = new HashSet<>();
for (int i = 0; i < 50; ++i) {
if (returnedPlayers.size() >= 5) {
break;
@Test
void getRandomPlayer() {
try (MockedStatic<Bukkit> server = Mockito.mockStatic(Bukkit.class)) {
List<Player> players = new ArrayList<>(10);
for (int i = 0; i < 10; ++i) {
Player player = createMockPlayer("Player_" + i);
players.add(player);
}
returnedPlayers.add(PlayerUtils.getRandomPlayer());
}
server.when(Bukkit::getOnlinePlayers).thenReturn(players);
assertTrue(returnedPlayers.size() >= 5);
Set<Player> returnedPlayers = new HashSet<>();
for (int i = 0; i < 50; ++i) {
if (returnedPlayers.size() >= 5) {
break;
}
returnedPlayers.add(PlayerUtils.getRandomPlayer());
}
assertTrue(returnedPlayers.size() >= 5);
}
}
@Test
void giveItem() {
Player player = this.server.addPlayer();
PlayerInventory inventory = Mockito.mock(PlayerInventory.class);
InOrder inventoryInOrder = Mockito.inOrder(inventory);
PlayerUtils.giveItem(player, new ItemStack(Material.STONE));
assertTrue(player.getInventory().contains(Material.STONE, 1));
Player player = createMockPlayer("Player");
Mockito.when(player.getInventory()).thenReturn(inventory);
Mockito.when(player.isOnline()).thenReturn(true);
PlayerUtils.giveItem(player, new ItemStack(Material.GRASS_BLOCK), new ItemStack(Material.GRASS_BLOCK));
assertTrue(player.getInventory().contains(Material.GRASS_BLOCK, 2));
ItemStack itemToAdd = Mockito.mock(ItemStack.class);
PlayerUtils.giveItem(player, Arrays.asList(new ItemStack(Material.WHEAT_SEEDS), new ItemStack(Material.WHEAT_SEEDS)));
assertTrue(player.getInventory().contains(Material.WHEAT_SEEDS, 2));
PlayerUtils.giveItem(player, itemToAdd);
inventoryInOrder.verify(inventory).addItem(itemToAdd);
inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any());
}
@Test
void giveItemOnFullInventory() {
PlayerMock player = this.server.addPlayer();
void giveItem_Array() {
PlayerInventory inventory = Mockito.mock(PlayerInventory.class);
InOrder inventoryInOrder = Mockito.inOrder(inventory);
fillInventory(player);
Player player = createMockPlayer("Player");
Mockito.when(player.getInventory()).thenReturn(inventory);
Mockito.when(player.isOnline()).thenReturn(true);
int entityCount = this.server.getEntities().size();
PlayerUtils.giveItem(player, new ItemStack(Material.STONE));
assertEquals(entityCount + 1, this.server.getEntities().size());
ItemStack[] itemsToAdd = new ItemStack[] {Mockito.mock(ItemStack.class), Mockito.mock(ItemStack.class)};
entityCount = this.server.getEntities().size();
PlayerUtils.giveItem(player, new ItemStack(Material.GRASS_BLOCK), new ItemStack(Material.GRASS_BLOCK));
assertEquals(entityCount + 2, this.server.getEntities().size());
PlayerUtils.giveItem(player, itemsToAdd);
inventoryInOrder.verify(inventory).addItem(itemsToAdd);
inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any());
}
entityCount = this.server.getEntities().size();
PlayerUtils.giveItem(player, Arrays.asList(new ItemStack(Material.WHEAT_SEEDS), new ItemStack(Material.WHEAT_SEEDS), new ItemStack(Material.WHEAT_SEEDS)));
assertEquals(entityCount + 3, this.server.getEntities().size());
@Test
void giveItem_List() {
PlayerInventory inventory = Mockito.mock(PlayerInventory.class);
InOrder inventoryInOrder = Mockito.inOrder(inventory);
Player player = createMockPlayer("Player");
Mockito.when(player.getInventory()).thenReturn(inventory);
Mockito.when(player.isOnline()).thenReturn(true);
ItemStack[] itemsToAdd = new ItemStack[] {Mockito.mock(ItemStack.class), Mockito.mock(ItemStack.class)};
PlayerUtils.giveItem(player, Arrays.asList(itemsToAdd));
inventoryInOrder.verify(inventory).addItem(itemsToAdd);
inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any());
}
@Test
void giveItem_FullInventory() {
ItemStack itemToAdd = Mockito.mock(ItemStack.class);
PlayerInventory inventory = Mockito.mock(PlayerInventory.class);
Mockito.when(inventory.addItem(itemToAdd)).thenReturn(new HashMap<Integer, ItemStack>() {{
put(0, itemToAdd);
}});
InOrder inventoryInOrder = Mockito.inOrder(inventory);
Player player = createMockPlayer("Player");
Mockito.when(player.getInventory()).thenReturn(inventory);
Mockito.when(player.isOnline()).thenReturn(true);
World world = Mockito.mock(World.class);
InOrder worldInOrder = Mockito.inOrder(world);
Mockito.when(player.getWorld()).thenReturn(world);
PlayerUtils.giveItem(player, itemToAdd);
inventoryInOrder.verify(inventory).addItem(itemToAdd);
inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any());
worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemToAdd));
worldInOrder.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any());
}
@Test
void giveItem_FullInventory_Array() {
ItemStack[] itemsToAdd = new ItemStack[] {Mockito.mock(ItemStack.class), Mockito.mock(ItemStack.class)};
PlayerInventory inventory = Mockito.mock(PlayerInventory.class);
Mockito.when(inventory.addItem(Mockito.any())).thenReturn(new HashMap<Integer, ItemStack>() {{
put(0, itemsToAdd[0]);
put(1, itemsToAdd[1]);
}});
InOrder inventoryInOrder = Mockito.inOrder(inventory);
Player player = createMockPlayer("Player");
Mockito.when(player.getInventory()).thenReturn(inventory);
Mockito.when(player.isOnline()).thenReturn(true);
World world = Mockito.mock(World.class);
InOrder worldInOrder = Mockito.inOrder(world);
Mockito.when(player.getWorld()).thenReturn(world);
PlayerUtils.giveItem(player, itemsToAdd);
inventoryInOrder.verify(inventory).addItem(itemsToAdd);
inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any());
worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemsToAdd[0]));
worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemsToAdd[1]));
worldInOrder.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any());
}
@Test
void giveItem_FullInventory_List() {
ItemStack[] itemsToAdd = new ItemStack[] {Mockito.mock(ItemStack.class), Mockito.mock(ItemStack.class)};
PlayerInventory inventory = Mockito.mock(PlayerInventory.class);
Mockito.when(inventory.addItem(Mockito.any())).thenReturn(new HashMap<Integer, ItemStack>() {{
put(0, itemsToAdd[0]);
put(1, itemsToAdd[1]);
}});
InOrder inventoryInOrder = Mockito.inOrder(inventory);
Player player = createMockPlayer("Player");
Mockito.when(player.getInventory()).thenReturn(inventory);
Mockito.when(player.isOnline()).thenReturn(true);
World world = Mockito.mock(World.class);
InOrder worldInOrder = Mockito.inOrder(world);
Mockito.when(player.getWorld()).thenReturn(world);
PlayerUtils.giveItem(player, Arrays.asList(itemsToAdd));
inventoryInOrder.verify(inventory).addItem(itemsToAdd);
inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any());
worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemsToAdd[0]));
worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemsToAdd[1]));
worldInOrder.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any());
}
@Disabled("Test is incomplete")
@Test
void getNumberFromPermission() {
Player player = this.server.addPlayer();
Player player = createMockPlayer("Player");
assertEquals(-1, PlayerUtils.getNumberFromPermission(player, "example.plugin.feature", -1));
}
private void fillInventory(Player player) {
ItemStack[] contents = new ItemStack[player.getInventory().getContents().length];
private Player createMockPlayer(String name) {
return createMockPlayer(name, name);
}
for (int i = 0; i < contents.length; ++i) {
contents[i] = new ItemStack(Material.BARRIER);
}
private Player createMockPlayer(String name, String displayName) {
Player player = Mockito.mock(Player.class);
Mockito.when(player.getName()).thenReturn(name);
Mockito.when(player.getDisplayName()).thenReturn(displayName);
player.getInventory().setContents(contents);
return player;
}
}

1001
LICENSE

File diff suppressed because it is too large Load Diff

View File

@ -7,18 +7,17 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore-NMS-API</artifactId>
<packaging>jar</packaging>
<dependencies>
<!--suppress VulnerableLibrariesLocal -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.17</version>
<artifactId>spigot-api</artifactId>
<version>1.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@ -26,6 +25,7 @@
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-Compatibility</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,20 @@
package com.songoda.core.nms;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.entity.NMSPlayer;
import com.songoda.core.nms.nbt.NBTCore;
import com.songoda.core.nms.world.NmsWorldBorder;
import com.songoda.core.nms.world.WorldCore;
import org.jetbrains.annotations.NotNull;
public interface NmsImplementations {
@NotNull NMSPlayer getPlayer();
@NotNull WorldCore getWorld();
@NotNull NmsWorldBorder getWorldBorder();
@NotNull AnvilCore getAnvil();
@NotNull NBTCore getNbt();
}

View File

@ -0,0 +1,12 @@
package com.songoda.core.nms.world;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public interface NmsWorldBorder {
void send(Player player, BorderColor color, double size, Location center);
enum BorderColor {
BLUE, GREEN, RED
}
}

View File

@ -1,9 +1,20 @@
package com.songoda.core.nms.world;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import java.util.List;
public interface SWorld {
List<LivingEntity> getLivingEntities();
/**
* Set a block to a certain type by updating the block directly in the NMS chunk.
* <br>
* The chunk must be loaded and players must relog if they have the chunk loaded in order to use this method.
* (F3+A is not enough)
*/
// TODO: Check if FabledSkyBlock *really* needs this method and if it can be removed.
// Would make thinks less complicated and I kinda cannot imagine it being *that* much faster to be worth it?
void setBlockFast(int x, int y, int z, Material material);
}

View File

@ -3,13 +3,17 @@ package com.songoda.core.nms.world;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import org.jetbrains.annotations.NotNull;
public interface WorldCore {
/**
* @deprecated Use {@link #getSpawner(Location)} instead
*/
@Deprecated
SSpawner getSpawner(CreatureSpawner spawner);
SSpawner getSpawner(Location location);
@ -18,7 +22,7 @@ public interface WorldCore {
SWorld getWorld(World world);
BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException;
BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws ReflectiveOperationException;
/**
* Performs random ticks on a specific chunks.
@ -28,7 +32,9 @@ public interface WorldCore {
* @param bukkitChunk The chunk to tick
* @param tickAmount The number of blocks to tick per ChunkSection, normally referred to as <code>randomTickSpeed</code>
*/
void randomTickChunk(Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException;
void randomTickChunk(Chunk bukkitChunk, int tickAmount) throws ReflectiveOperationException;
void updateAdjacentComparators(@NotNull Block bukkitBlock);
/**
* Ticks all inactive spawners in a specific chunk ignoring the minimum required players within a specific range.<br>
@ -37,7 +43,7 @@ public interface WorldCore {
* @param chunk The chunk to tick the spawners in
* @param amount The amount of ticks to execute for each spawner
*/
default void tickInactiveSpawners(Chunk chunk, int amount) throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
default void tickInactiveSpawners(Chunk chunk, int amount) throws ReflectiveOperationException {
if (amount <= 0) return;
for (BlockState tileEntity : chunk.getTileEntities()) {

View File

@ -7,12 +7,10 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore-NMS-v1_10_R1</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
@ -26,12 +24,14 @@
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-API</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-Compatibility</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,55 @@
package com.songoda.core.nms.v1_10_R1;
import com.songoda.core.nms.NmsImplementations;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.entity.NMSPlayer;
import com.songoda.core.nms.nbt.NBTCore;
import com.songoda.core.nms.v1_10_R1.entity.NMSPlayerImpl;
import com.songoda.core.nms.v1_10_R1.nbt.NBTCoreImpl;
import com.songoda.core.nms.v1_10_R1.world.NmsWorldBorderImpl;
import com.songoda.core.nms.v1_10_R1.world.WorldCoreImpl;
import com.songoda.core.nms.world.NmsWorldBorder;
import com.songoda.core.nms.world.WorldCore;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class NmsImplementationsImpl implements NmsImplementations {
private final NMSPlayer player;
private final WorldCore world;
private final NmsWorldBorder worldBorder;
private final AnvilCore anvil;
private final NBTCore nbt;
public NmsImplementationsImpl() {
this.player = new NMSPlayerImpl();
this.world = new WorldCoreImpl();
this.worldBorder = new NmsWorldBorderImpl();
this.anvil = new com.songoda.core.nms.v1_10_R1.anvil.AnvilCore();
this.nbt = new NBTCoreImpl();
}
@Override
public @NotNull NMSPlayer getPlayer() {
return this.player;
}
@Override
public @NotNull WorldCore getWorld() {
return this.world;
}
@Override
public @NotNull NmsWorldBorder getWorldBorder() {
return this.worldBorder;
}
@Override
public @NotNull AnvilCore getAnvil() {
return this.anvil;
}
@Override
public @NotNull NBTCore getNbt() {
return this.nbt;
}
}

View File

@ -21,6 +21,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity {
@Override
public org.bukkit.entity.Entity spawn(Location location) {
String entityType = getNBTObject("entity_type").asString();
getKeys().remove("UUID");
Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14
((CraftWorld) location.getWorld()).getHandle(),

View File

@ -0,0 +1,35 @@
package com.songoda.core.nms.v1_10_R1.world;
import com.songoda.core.nms.world.NmsWorldBorder;
import net.minecraft.server.v1_10_R1.PacketPlayOutWorldBorder;
import net.minecraft.server.v1_10_R1.WorldBorder;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class NmsWorldBorderImpl implements NmsWorldBorder {
@Override
public void send(Player player, BorderColor color, double size, @NotNull Location center) {
Objects.requireNonNull(center.getWorld());
WorldBorder worldBorder = new WorldBorder();
worldBorder.world = ((CraftWorld) center.getWorld()).getHandle();
worldBorder.setCenter(center.getX(), center.getZ());
worldBorder.setSize(size);
worldBorder.setWarningTime(0);
worldBorder.setWarningDistance(0);
if (color == BorderColor.GREEN) {
worldBorder.transitionSizeBetween(size - 0.1D, size, Long.MAX_VALUE);
} else if (color == BorderColor.RED) {
worldBorder.transitionSizeBetween(size, size - 1.0D, Long.MAX_VALUE);
}
((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutWorldBorder(worldBorder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE));
}
}

View File

@ -1,17 +1,35 @@
package com.songoda.core.nms.v1_10_R1.world;
import com.songoda.core.nms.world.SWorld;
import net.minecraft.server.v1_10_R1.Block;
import net.minecraft.server.v1_10_R1.BlockPosition;
import net.minecraft.server.v1_10_R1.Chunk;
import net.minecraft.server.v1_10_R1.WorldServer;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
import org.bukkit.entity.LivingEntity;
import java.util.ArrayList;
import java.util.List;
public class SWorldImpl implements SWorld {
public SWorldImpl() {
private final World world;
public SWorldImpl(World world) {
this.world = world;
}
@Override
public List<LivingEntity> getLivingEntities() {
return new ArrayList<>();
return new ArrayList<>(); // FIXME
}
@Override
public void setBlockFast(int x, int y, int z, Material material) {
WorldServer serverLevel = ((CraftWorld) this.world).getHandle();
Chunk levelChunk = serverLevel.getChunkIfLoaded(x >> 4, z >> 4);
levelChunk.a(new BlockPosition(x & 0xF, y, z & 0xF), Block.getByCombinedId(0));
}
}

View File

@ -18,7 +18,11 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_10_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_10_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_10_R1.util.CraftMagicNumbers;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class WorldCoreImpl implements WorldCore {
@Override
@ -38,7 +42,7 @@ public class WorldCoreImpl implements WorldCore {
@Override
public SWorld getWorld(World world) {
return new SWorldImpl();
return new SWorldImpl(world);
}
@Override
@ -85,4 +89,14 @@ public class WorldCoreImpl implements WorldCore {
}
}
}
@Override
public void updateAdjacentComparators(@NotNull org.bukkit.block.Block bukkitBlock) {
CraftBlock craftBlock = (CraftBlock) bukkitBlock;
WorldServer serverLevel = ((CraftWorld) craftBlock.getWorld()).getHandle();
BlockPosition blockPos = new BlockPosition(craftBlock.getX(), craftBlock.getY(), craftBlock.getZ());
Block nmsBlock = CraftMagicNumbers.getBlock(bukkitBlock.getType());
serverLevel.updateAdjacentComparators(blockPos, nmsBlock);
}
}

View File

@ -7,12 +7,10 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore-NMS-v1_11_R1</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
@ -26,12 +24,14 @@
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-API</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-Compatibility</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,55 @@
package com.songoda.core.nms.v1_11_R1;
import com.songoda.core.nms.NmsImplementations;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.entity.NMSPlayer;
import com.songoda.core.nms.nbt.NBTCore;
import com.songoda.core.nms.v1_11_R1.entity.NMSPlayerImpl;
import com.songoda.core.nms.v1_11_R1.nbt.NBTCoreImpl;
import com.songoda.core.nms.v1_11_R1.world.NmsWorldBorderImpl;
import com.songoda.core.nms.v1_11_R1.world.WorldCoreImpl;
import com.songoda.core.nms.world.NmsWorldBorder;
import com.songoda.core.nms.world.WorldCore;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class NmsImplementationsImpl implements NmsImplementations {
private final NMSPlayer player;
private final WorldCore world;
private final NmsWorldBorder worldBorder;
private final AnvilCore anvil;
private final NBTCore nbt;
public NmsImplementationsImpl() {
this.player = new NMSPlayerImpl();
this.world = new WorldCoreImpl();
this.worldBorder = new NmsWorldBorderImpl();
this.anvil = new com.songoda.core.nms.v1_11_R1.anvil.AnvilCore();
this.nbt = new NBTCoreImpl();
}
@Override
public @NotNull NMSPlayer getPlayer() {
return this.player;
}
@Override
public @NotNull WorldCore getWorld() {
return this.world;
}
@Override
public @NotNull NmsWorldBorder getWorldBorder() {
return this.worldBorder;
}
@Override
public @NotNull AnvilCore getAnvil() {
return this.anvil;
}
@Override
public @NotNull NBTCore getNbt() {
return this.nbt;
}
}

View File

@ -22,6 +22,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity {
@Override
public org.bukkit.entity.Entity spawn(Location location) {
String entityType = getNBTObject("entity_type").asString();
getKeys().remove("UUID");
Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14
((CraftWorld) location.getWorld()).getHandle(),

View File

@ -0,0 +1,35 @@
package com.songoda.core.nms.v1_11_R1.world;
import com.songoda.core.nms.world.NmsWorldBorder;
import net.minecraft.server.v1_11_R1.PacketPlayOutWorldBorder;
import net.minecraft.server.v1_11_R1.WorldBorder;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_11_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class NmsWorldBorderImpl implements NmsWorldBorder {
@Override
public void send(Player player, BorderColor color, double size, @NotNull Location center) {
Objects.requireNonNull(center.getWorld());
WorldBorder worldBorder = new WorldBorder();
worldBorder.world = ((CraftWorld) center.getWorld()).getHandle();
worldBorder.setCenter(center.getX(), center.getZ());
worldBorder.setSize(size);
worldBorder.setWarningTime(0);
worldBorder.setWarningDistance(0);
if (color == BorderColor.GREEN) {
worldBorder.transitionSizeBetween(size - 0.1D, size, Long.MAX_VALUE);
} else if (color == BorderColor.RED) {
worldBorder.transitionSizeBetween(size, size - 1.0D, Long.MAX_VALUE);
}
((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutWorldBorder(worldBorder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE));
}
}

View File

@ -1,17 +1,35 @@
package com.songoda.core.nms.v1_11_R1.world;
import com.songoda.core.nms.world.SWorld;
import net.minecraft.server.v1_11_R1.Block;
import net.minecraft.server.v1_11_R1.BlockPosition;
import net.minecraft.server.v1_11_R1.Chunk;
import net.minecraft.server.v1_11_R1.WorldServer;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_11_R1.CraftWorld;
import org.bukkit.entity.LivingEntity;
import java.util.ArrayList;
import java.util.List;
public class SWorldImpl implements SWorld {
public SWorldImpl() {
private final World world;
public SWorldImpl(World world) {
this.world = world;
}
@Override
public List<LivingEntity> getLivingEntities() {
return new ArrayList<>();
return new ArrayList<>(); // FIXME
}
@Override
public void setBlockFast(int x, int y, int z, Material material) {
WorldServer serverLevel = ((CraftWorld) this.world).getHandle();
Chunk levelChunk = serverLevel.getChunkIfLoaded(x >> 4, z >> 4);
levelChunk.a(new BlockPosition(x & 0xF, y, z & 0xF), Block.getByCombinedId(0));
}
}

View File

@ -18,7 +18,11 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.craftbukkit.v1_11_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_11_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_11_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_11_R1.util.CraftMagicNumbers;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class WorldCoreImpl implements WorldCore {
@Override
@ -38,7 +42,7 @@ public class WorldCoreImpl implements WorldCore {
@Override
public SWorld getWorld(World world) {
return new SWorldImpl();
return new SWorldImpl(world);
}
@Override
@ -85,4 +89,14 @@ public class WorldCoreImpl implements WorldCore {
}
}
}
@Override
public void updateAdjacentComparators(@NotNull org.bukkit.block.Block bukkitBlock) {
CraftBlock craftBlock = (CraftBlock) bukkitBlock;
WorldServer serverLevel = ((CraftWorld) craftBlock.getWorld()).getHandle();
BlockPosition blockPos = new BlockPosition(craftBlock.getX(), craftBlock.getY(), craftBlock.getZ());
Block nmsBlock = CraftMagicNumbers.getBlock(bukkitBlock.getType());
serverLevel.updateAdjacentComparators(blockPos, nmsBlock);
}
}

View File

@ -7,12 +7,10 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore-NMS-v1_12_R1</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
@ -26,12 +24,14 @@
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-API</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-Compatibility</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,55 @@
package com.songoda.core.nms.v1_12_R1;
import com.songoda.core.nms.NmsImplementations;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.entity.NMSPlayer;
import com.songoda.core.nms.nbt.NBTCore;
import com.songoda.core.nms.v1_12_R1.entity.NMSPlayerImpl;
import com.songoda.core.nms.v1_12_R1.nbt.NBTCoreImpl;
import com.songoda.core.nms.v1_12_R1.world.NmsWorldBorderImpl;
import com.songoda.core.nms.v1_12_R1.world.WorldCoreImpl;
import com.songoda.core.nms.world.NmsWorldBorder;
import com.songoda.core.nms.world.WorldCore;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class NmsImplementationsImpl implements NmsImplementations {
private final NMSPlayer player;
private final WorldCore world;
private final NmsWorldBorder worldBorder;
private final AnvilCore anvil;
private final NBTCore nbt;
public NmsImplementationsImpl() {
this.player = new NMSPlayerImpl();
this.world = new WorldCoreImpl();
this.worldBorder = new NmsWorldBorderImpl();
this.anvil = new com.songoda.core.nms.v1_12_R1.anvil.AnvilCore();
this.nbt = new NBTCoreImpl();
}
@Override
public @NotNull NMSPlayer getPlayer() {
return this.player;
}
@Override
public @NotNull WorldCore getWorld() {
return this.world;
}
@Override
public @NotNull NmsWorldBorder getWorldBorder() {
return this.worldBorder;
}
@Override
public @NotNull AnvilCore getAnvil() {
return this.anvil;
}
@Override
public @NotNull NBTCore getNbt() {
return this.nbt;
}
}

View File

@ -22,6 +22,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity {
@Override
public org.bukkit.entity.Entity spawn(Location location) {
String entityType = getNBTObject("entity_type").asString();
getKeys().remove("UUID");
Entity spawned = ItemMonsterEgg.spawnCreature( // Changed since 1.14
((CraftWorld) location.getWorld()).getHandle(),

View File

@ -0,0 +1,35 @@
package com.songoda.core.nms.v1_12_R1.world;
import com.songoda.core.nms.world.NmsWorldBorder;
import net.minecraft.server.v1_12_R1.PacketPlayOutWorldBorder;
import net.minecraft.server.v1_12_R1.WorldBorder;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class NmsWorldBorderImpl implements NmsWorldBorder {
@Override
public void send(Player player, BorderColor color, double size, @NotNull Location center) {
Objects.requireNonNull(center.getWorld());
WorldBorder worldBorder = new WorldBorder();
worldBorder.world = ((CraftWorld) center.getWorld()).getHandle();
worldBorder.setCenter(center.getX(), center.getZ());
worldBorder.setSize(size);
worldBorder.setWarningTime(0);
worldBorder.setWarningDistance(0);
if (color == BorderColor.GREEN) {
worldBorder.transitionSizeBetween(size - 0.1D, size, Long.MAX_VALUE);
} else if (color == BorderColor.RED) {
worldBorder.transitionSizeBetween(size, size - 1.0D, Long.MAX_VALUE);
}
((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutWorldBorder(worldBorder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE));
}
}

View File

@ -1,17 +1,35 @@
package com.songoda.core.nms.v1_12_R1.world;
import com.songoda.core.nms.world.SWorld;
import net.minecraft.server.v1_12_R1.Block;
import net.minecraft.server.v1_12_R1.BlockPosition;
import net.minecraft.server.v1_12_R1.Chunk;
import net.minecraft.server.v1_12_R1.WorldServer;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
import org.bukkit.entity.LivingEntity;
import java.util.ArrayList;
import java.util.List;
public class SWorldImpl implements SWorld {
public SWorldImpl() {
private final World world;
public SWorldImpl(World world) {
this.world = world;
}
@Override
public List<LivingEntity> getLivingEntities() {
return new ArrayList<>();
return new ArrayList<>(); // FIXME
}
@Override
public void setBlockFast(int x, int y, int z, Material material) {
WorldServer serverLevel = ((CraftWorld) this.world).getHandle();
Chunk levelChunk = serverLevel.getChunkIfLoaded(x >> 4, z >> 4);
levelChunk.a(new BlockPosition(x & 0xF, y, z & 0xF), Block.getByCombinedId(0));
}
}

View File

@ -18,7 +18,11 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.craftbukkit.v1_12_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_12_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_12_R1.util.CraftMagicNumbers;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class WorldCoreImpl implements WorldCore {
@Override
@ -38,7 +42,7 @@ public class WorldCoreImpl implements WorldCore {
@Override
public SWorld getWorld(World world) {
return new SWorldImpl();
return new SWorldImpl(world);
}
@Override
@ -85,4 +89,14 @@ public class WorldCoreImpl implements WorldCore {
}
}
}
@Override
public void updateAdjacentComparators(@NotNull org.bukkit.block.Block bukkitBlock) {
CraftBlock craftBlock = (CraftBlock) bukkitBlock;
WorldServer serverLevel = ((CraftWorld) craftBlock.getWorld()).getHandle();
BlockPosition blockPos = new BlockPosition(craftBlock.getX(), craftBlock.getY(), craftBlock.getZ());
Block nmsBlock = CraftMagicNumbers.getBlock(bukkitBlock.getType());
serverLevel.updateAdjacentComparators(blockPos, nmsBlock);
}
}

View File

@ -7,12 +7,10 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore-NMS-v1_13_R1</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
@ -26,12 +24,14 @@
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-API</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-Compatibility</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,55 @@
package com.songoda.core.nms.v1_13_R1;
import com.songoda.core.nms.NmsImplementations;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.entity.NMSPlayer;
import com.songoda.core.nms.nbt.NBTCore;
import com.songoda.core.nms.v1_13_R1.entity.NMSPlayerImpl;
import com.songoda.core.nms.v1_13_R1.nbt.NBTCoreImpl;
import com.songoda.core.nms.v1_13_R1.world.NmsWorldBorderImpl;
import com.songoda.core.nms.v1_13_R1.world.WorldCoreImpl;
import com.songoda.core.nms.world.NmsWorldBorder;
import com.songoda.core.nms.world.WorldCore;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class NmsImplementationsImpl implements NmsImplementations {
private final NMSPlayer player;
private final WorldCore world;
private final NmsWorldBorder worldBorder;
private final AnvilCore anvil;
private final NBTCore nbt;
public NmsImplementationsImpl() {
this.player = new NMSPlayerImpl();
this.world = new WorldCoreImpl();
this.worldBorder = new NmsWorldBorderImpl();
this.anvil = new com.songoda.core.nms.v1_13_R1.anvil.AnvilCore();
this.nbt = new NBTCoreImpl();
}
@Override
public @NotNull NMSPlayer getPlayer() {
return this.player;
}
@Override
public @NotNull WorldCore getWorld() {
return this.world;
}
@Override
public @NotNull NmsWorldBorder getWorldBorder() {
return this.worldBorder;
}
@Override
public @NotNull AnvilCore getAnvil() {
return this.anvil;
}
@Override
public @NotNull NBTCore getNbt() {
return this.nbt;
}
}

View File

@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity {
@Override
public org.bukkit.entity.Entity spawn(Location location) {
String entityType = getNBTObject("entity_type").asString();
getKeys().remove("UUID");
Optional<EntityTypes<?>> optionalEntity = Optional.ofNullable(EntityTypes.a(entityType)); // Changed since 1.13.2
if (optionalEntity.isPresent()) {

View File

@ -0,0 +1,35 @@
package com.songoda.core.nms.v1_13_R1.world;
import com.songoda.core.nms.world.NmsWorldBorder;
import net.minecraft.server.v1_13_R1.PacketPlayOutWorldBorder;
import net.minecraft.server.v1_13_R1.WorldBorder;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_13_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class NmsWorldBorderImpl implements NmsWorldBorder {
@Override
public void send(Player player, BorderColor color, double size, @NotNull Location center) {
Objects.requireNonNull(center.getWorld());
WorldBorder worldBorder = new WorldBorder();
worldBorder.world = ((CraftWorld) center.getWorld()).getHandle();
worldBorder.setCenter(center.getX(), center.getZ());
worldBorder.setSize(size);
worldBorder.setWarningTime(0);
worldBorder.setWarningDistance(0);
if (color == BorderColor.GREEN) {
worldBorder.transitionSizeBetween(size - 0.1D, size, Long.MAX_VALUE);
} else if (color == BorderColor.RED) {
worldBorder.transitionSizeBetween(size, size - 1.0D, Long.MAX_VALUE);
}
((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutWorldBorder(worldBorder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE));
}
}

View File

@ -1,17 +1,37 @@
package com.songoda.core.nms.v1_13_R1.world;
import com.songoda.core.nms.world.SWorld;
import net.minecraft.server.v1_13_R1.BlockPosition;
import net.minecraft.server.v1_13_R1.Chunk;
import net.minecraft.server.v1_13_R1.IBlockData;
import net.minecraft.server.v1_13_R1.WorldServer;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_13_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_13_R1.block.data.CraftBlockData;
import org.bukkit.entity.LivingEntity;
import java.util.ArrayList;
import java.util.List;
public class SWorldImpl implements SWorld {
public SWorldImpl() {
private final World world;
public SWorldImpl(World world) {
this.world = world;
}
@Override
public List<LivingEntity> getLivingEntities() {
return new ArrayList<>();
return new ArrayList<>(); // FIXME
}
@Override
public void setBlockFast(int x, int y, int z, Material material) {
WorldServer serverLevel = ((CraftWorld) this.world).getHandle();
Chunk levelChunk = serverLevel.getChunkIfLoaded(x >> 4, z >> 4);
IBlockData blockState = ((CraftBlockData) material.createBlockData()).getState();
levelChunk.a(new BlockPosition(x & 0xF, y, z & 0xF), blockState, true);
}
}

View File

@ -16,9 +16,12 @@ import net.minecraft.server.v1_13_R1.MobSpawnerAbstract;
import net.minecraft.server.v1_13_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.craftbukkit.v1_13_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_13_R1.block.CraftBlock;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class WorldCoreImpl implements WorldCore {
@Override
@ -38,7 +41,7 @@ public class WorldCoreImpl implements WorldCore {
@Override
public SWorld getWorld(World world) {
return new SWorldImpl();
return new SWorldImpl(world);
}
@Override
@ -89,4 +92,12 @@ public class WorldCoreImpl implements WorldCore {
}
}
}
@Override
public void updateAdjacentComparators(@NotNull Block bukkitBlock) {
CraftBlock craftBlock = (CraftBlock) bukkitBlock;
WorldServer serverLevel = craftBlock.getCraftWorld().getHandle();
serverLevel.updateAdjacentComparators(craftBlock.getPosition(), craftBlock.getNMS().getBlock());
}
}

View File

@ -7,12 +7,10 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore-NMS-v1_13_R2</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
@ -26,12 +24,14 @@
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-API</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-Compatibility</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,55 @@
package com.songoda.core.nms.v1_13_R2;
import com.songoda.core.nms.NmsImplementations;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.entity.NMSPlayer;
import com.songoda.core.nms.nbt.NBTCore;
import com.songoda.core.nms.v1_13_R2.entity.NMSPlayerImpl;
import com.songoda.core.nms.v1_13_R2.nbt.NBTCoreImpl;
import com.songoda.core.nms.v1_13_R2.world.NmsWorldBorderImpl;
import com.songoda.core.nms.v1_13_R2.world.WorldCoreImpl;
import com.songoda.core.nms.world.NmsWorldBorder;
import com.songoda.core.nms.world.WorldCore;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class NmsImplementationsImpl implements NmsImplementations {
private final NMSPlayer player;
private final WorldCore world;
private final NmsWorldBorder worldBorder;
private final AnvilCore anvil;
private final NBTCore nbt;
public NmsImplementationsImpl() {
this.player = new NMSPlayerImpl();
this.world = new WorldCoreImpl();
this.worldBorder = new NmsWorldBorderImpl();
this.anvil = new com.songoda.core.nms.v1_13_R2.anvil.AnvilCore();
this.nbt = new NBTCoreImpl();
}
@Override
public @NotNull NMSPlayer getPlayer() {
return this.player;
}
@Override
public @NotNull WorldCore getWorld() {
return this.world;
}
@Override
public @NotNull NmsWorldBorder getWorldBorder() {
return this.worldBorder;
}
@Override
public @NotNull AnvilCore getAnvil() {
return this.anvil;
}
@Override
public @NotNull NBTCore getNbt() {
return this.nbt;
}
}

View File

@ -24,6 +24,7 @@ public class NBTEntityImpl extends NBTCompoundImpl implements NBTEntity {
@Override
public org.bukkit.entity.Entity spawn(Location location) {
String entityType = getNBTObject("entity_type").asString();
getKeys().remove("UUID");
Optional<EntityTypes<?>> optionalEntity = Optional.ofNullable(EntityTypes.a(entityType)); // Changed since 1.13.2
if (optionalEntity.isPresent()) {

View File

@ -0,0 +1,35 @@
package com.songoda.core.nms.v1_13_R2.world;
import com.songoda.core.nms.world.NmsWorldBorder;
import net.minecraft.server.v1_13_R2.PacketPlayOutWorldBorder;
import net.minecraft.server.v1_13_R2.WorldBorder;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class NmsWorldBorderImpl implements NmsWorldBorder {
@Override
public void send(Player player, BorderColor color, double size, @NotNull Location center) {
Objects.requireNonNull(center.getWorld());
WorldBorder worldBorder = new WorldBorder();
worldBorder.world = ((CraftWorld) center.getWorld()).getHandle();
worldBorder.setCenter(center.getX(), center.getZ());
worldBorder.setSize(size);
worldBorder.setWarningTime(0);
worldBorder.setWarningDistance(0);
if (color == BorderColor.GREEN) {
worldBorder.transitionSizeBetween(size - 0.1D, size, Long.MAX_VALUE);
} else if (color == BorderColor.RED) {
worldBorder.transitionSizeBetween(size, size - 1.0D, Long.MAX_VALUE);
}
((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutWorldBorder(worldBorder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE));
}
}

View File

@ -1,17 +1,37 @@
package com.songoda.core.nms.v1_13_R2.world;
import com.songoda.core.nms.world.SWorld;
import net.minecraft.server.v1_13_R2.BlockPosition;
import net.minecraft.server.v1_13_R2.Chunk;
import net.minecraft.server.v1_13_R2.IBlockData;
import net.minecraft.server.v1_13_R2.WorldServer;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_13_R2.block.data.CraftBlockData;
import org.bukkit.entity.LivingEntity;
import java.util.ArrayList;
import java.util.List;
public class SWorldImpl implements SWorld {
public SWorldImpl() {
private final World world;
public SWorldImpl(World world) {
this.world = world;
}
@Override
public List<LivingEntity> getLivingEntities() {
return new ArrayList<>();
return new ArrayList<>(); // FIXME
}
@Override
public void setBlockFast(int x, int y, int z, Material material) {
WorldServer serverLevel = ((CraftWorld) this.world).getHandle();
Chunk levelChunk = serverLevel.getChunkIfLoaded(x >> 4, z >> 4);
IBlockData blockState = ((CraftBlockData) material.createBlockData()).getState();
levelChunk.setType(new BlockPosition(x & 0xF, y, z & 0xF), blockState, true);
}
}

View File

@ -16,9 +16,12 @@ import net.minecraft.server.v1_13_R2.MobSpawnerAbstract;
import net.minecraft.server.v1_13_R2.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.craftbukkit.v1_13_R2.CraftChunk;
import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlock;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class WorldCoreImpl implements WorldCore {
@Override
@ -38,7 +41,7 @@ public class WorldCoreImpl implements WorldCore {
@Override
public SWorld getWorld(World world) {
return new SWorldImpl();
return new SWorldImpl(world);
}
@Override
@ -96,4 +99,12 @@ public class WorldCoreImpl implements WorldCore {
chunk.world.methodProfiler.exit();
}
@Override
public void updateAdjacentComparators(@NotNull Block bukkitBlock) {
CraftBlock craftBlock = (CraftBlock) bukkitBlock;
WorldServer serverLevel = craftBlock.getCraftWorld().getHandle();
serverLevel.updateAdjacentComparators(craftBlock.getPosition(), craftBlock.getNMS().getBlock());
}
}

View File

@ -7,12 +7,10 @@
<parent>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore-Modules</artifactId>
<version>2.6.15-DEV</version>
<version>2.6.22</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>SongodaCore-NMS-v1_14_R1</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
@ -26,12 +24,14 @@
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-NMS-API</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SongodaCore-Compatibility</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

Some files were not shown because too many files have changed in this diff Show More