Compare commits

...
393 Commits
Author SHA1 Message Date
NotAlexNoyle 22d9b5a6ec Point submodules at canonical Gitea repositories 2026-11-01 12:49:58 -05:00
NotAlexNoyle e24ef5edd3 Update canonical Gitea links 2026-10-31 14:18:03 -04:00
NotAlexNoyle 372633030f Update canonical Gitea links 2026-10-31 11:40:50 -04:00
NotAlexNoyle 5dcf38f995 Update canonical Gitea links 2026-10-31 11:40:49 -04:00
NotAlexNoyle dae014ed04 Exclude CODEOWNERS from language statistics 2026-10-31 09:54:59 -04:00
NotAlexNoyle c7d013813b Add CODEOWNERS (one staff approval) 2026-10-31 09:54:59 -04:00
NotAlexNoyle a737f3c872 Fix SLF4J warnings 2026-10-18 16:17:33 -04:00
NotAlexNoyle fa96da3bb2 Update Chat-OG 2026-10-18 15:57:47 -04:00
NotAlexNoyle 83c16f9a0d Use temp Chat-OG 2026-10-18 15:28:36 -04:00
NotAlexNoyle c812be3475 Update dependencies as projects 2026-10-18 15:07:12 -04:00
NotAlexNoyle ed44dcf601 Update dependencies 2026-10-18 13:09:15 -04:00
NotAlexNoyle a4d1d20690 Update MyWorlds 2026-10-02 11:52:48 -04:00
NotAlexNoyle ee6dfaaa8f Better game rules 2026-09-16 11:38:35 -04:00
NotAlexNoyle b713835f21 Fix floor change operation 2026-09-14 19:37:56 -04:00
NotAlexNoyle 1ecf17dfab new scoreboard 2026-09-14 19:23:15 -04:00
NotAlexNoyle 477e85aab6 Normalize scoreboard 2026-09-14 18:27:00 -04:00
NotAlexNoyle a035539475 Improve inventory handling 2026-09-14 11:16:01 -04:00
NotAlexNoyle a2ac0ddf23 Fix maps 2026-09-14 10:50:34 -04:00
NotAlexNoyle 16be8878f7 Update Utilities-OG 2026-09-14 01:59:10 -04:00
NotAlexNoyle 1d568fb8af Bundled map configs 2026-09-14 00:11:59 -04:00
NotAlexNoyle a0d849bcc0 Harmonize hub commands 2026-09-12 19:06:32 -04:00
NotAlexNoyle f021b541a6 Update BuildBattle-OG 2026-09-12 09:43:21 -04:00
NotAlexNoyle cf5df93928 Add MiniPlaceholders 2026-08-24 11:19:17 -04:00
NotAlexNoyle 99152f387c Update MyWorlds API 2026-08-19 10:03:27 -04:00
NotAlexNoyle 1a98750dc7 Update README.md 2026-08-19 07:46:00 -04:00
NotAlexNoyle 4d1018a991 Normalize with TheHerobrine-OG and Splegg-OG more 2026-08-17 13:44:52 -04:00
NotAlexNoyle 954330c889 Added /bbjoin, /bbforcestart, and a /v+/vote listener driving the existing theme poll (theme hidden in Guess The Build); renamed the arena id to BB1; added a Chat-OG formatter; started capturing return locations for players entering an arena world by any route, plus a respawn safety net; and fixed an onDisable ordering bug that let GameModeInventories swap mid-restore on /reload. 2026-08-11 14:08:38 -04:00
NotAlexNoyle db862b1717 TrueOG stack compatibility 2026-08-05 17:08:29 -04:00
NotAlexNoyle 1bf101e168 MyWorlds compatibility 2026-07-31 13:12:27 -04:00
NotAlexNoyle f894145c8b Formatting with spotless 2026-07-22 19:11:36 -04:00
NotAlexNoyle 25d06428b8 Merge pull request #3 from true-og/agent/suppress-unsupported-fork-warning
Suppress unsupported fork startup warning
2026-07-22 19:02:43 -04:00
NotAlexNoyle ab59522876 Suppress unsupported fork warning 2026-07-22 19:01:31 -04:00
NotAlexNoyle d4c4b02865 Fix powerups.yml 2026-06-17 13:47:14 -04:00
NotAlexNoyle b2720c449e Suppress console noise 2026-06-04 11:54:43 -04:00
NotAlexNoyle f5208d35b0 Bundle powerups.yml 2026-05-25 11:53:51 -04:00
NotAlexNoyle f345e5163a Return player to previous location 2026-05-20 05:51:47 -04:00
NotAlexNoyle 9020f85e3d v5.1.4 update 2026-05-20 05:02:42 -04:00
NotAlexNoyle 0e188de320 Improved world management 2026-05-17 22:38:30 -04:00
NotAlexNoyle 0c1bceeb3c Update build.gradle.kts 2026-04-27 14:27:27 -04:00
NotAlexNoyle ee3bf7b9ac New BKCommonLibs 2026-04-27 14:23:02 -04:00
NotAlexNoyle d2eb71c74e Remove vault 2026-04-24 14:19:42 -04:00
NotAlexNoyle 1f580609f0 Suppress minigamesbox annoying console messages 2026-04-23 14:32:10 -04:00
NotAlexNoyle 52b9e1ac24 Fix head cache 2026-04-13 04:22:58 -04:00
NotAlexNoyle 712e2a79c8 Update for new MyWorlds fork 2026-04-06 03:19:38 -04:00
NotAlexNoyle 303ff7c2e1 Fix MyWorlds fork compatibility 2026-04-02 13:49:43 -04:00
NotAlexNoyle 2f80cd6886 Backport to 1.19.4 MyWorlds API 2026-04-01 14:46:00 -04:00
NotAlexNoyle 2ba0ccaffa Add compatibility with MyWorlds 2026-03-30 07:29:19 -04:00
NotAlexNoyle acb5dae6a7 Fix two runtime errors 2026-03-30 04:03:08 -04:00
NotAlexNoyle 9425f74967 Fix runtime errors 2026-03-25 10:55:24 -04:00
NotAlexNoyle f8f4c4af6d Merge pull request #2 from true-og/codex/rename-project-to-buildbattle-og
Rename project to BuildBattle-OG
2026-03-18 12:14:18 -04:00
NotAlexNoyle ee30eb0569 Rename project to BuildBattle-OG 2026-03-18 12:12:49 -04:00
NotAlexNoyle f9d93a6bd4 Formatting 2026-03-18 05:36:45 -04:00
NotAlexNoyle 3eb333310e Finish gradle migration 2026-03-18 05:34:24 -04:00
NotAlexNoyle 979a9ec7fa Merge pull request #1 from true-og/codex/convert-minecraft-plugin-from-maven-to-gradle
Migrate BuildBattle from Maven to Gradle (Purpur 1.19.4, GraalVM 17)
2026-03-18 05:28:39 -04:00
NotAlexNoyle e611976cd6 Migrate build from Maven to Gradle 2026-03-18 05:26:35 -04:00
NotAlexNoyle 88428cb88f Merge branch 'Plugily-Projects:master' into master 2026-01-20 21:47:54 +00:00
NotAlexNoyle 24e26a6896 Add license to root (#115) 2026-01-20 22:32:52 +01:00
NotAlexNoyle 149163a360 Add license to root 2026-01-19 10:18:26 -05:00
version-bump[github-action] 4d4057cd7a Bump version from 5.1.2-SNAPSHOT3 to 5.1.3 2026-01-17 22:47:11 +00:00
Tigerpanzer_02andversion-bump[github-action] 4533d9b441 #patch Added support for 1.21.9-11 (#114)
Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2026-01-17 23:46:51 +01:00
version-bump[github-action] 26c961bb88 Bump version from 5.1.1-SNAPSHOT2 to 5.1.2 2025-07-22 19:40:41 +00:00
Tigerpanzer_02andversion-bump[github-action] 7ade50fd23 #patch 5.1.2 Fixed InventoryView and Vehicles (#110)
* Bump version from 5.1.1 to 5.1.1-SNAPSHOT0

* Fixed vehicle moving outside of arena plots and other worlds!

* Fixed InventoryView not interface onItemMove

* Fixed Method 'org.bukkit.block.banner.PatternType[] org.bukkit.block.banner.PatternType.values()' must be Methodref constant

* Fixed InventoryView not interface on getGui @VoteMenu

* Bump version from 5.1.1-SNAPSHOT0 to 5.1.1-SNAPSHOT1

* Updated CHANGELOG.md

* Bump version from 5.1.1-SNAPSHOT1 to 5.1.1-SNAPSHOT2

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2025-07-22 21:40:10 +02:00
version-bump[github-action] bd12269dc9 Bump version from 5.1.0-SNAPSHOT1 to 5.1.1 2025-07-15 19:20:05 +00:00
Tigerpanzer_02andversion-bump[github-action] 3142f28258 #patch small bug fix (#108)
* Bump version from 5.1.0 to 5.1.0-SNAPSHOT0

* Fixed bba ForcePlayArgument on console without Theme name

* Fixed water flow on other worlds than the plots are

* Bump version from 5.1.0-SNAPSHOT0 to 5.1.0-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2025-07-15 21:19:46 +02:00
version-bump[github-action] 616cb5f35c Bump version from 5.0.15-SNAPSHOT18 to 5.1.0 2025-07-14 21:20:51 +00:00
Tigerpanzer_02andversion-bump[github-action] d021381dc2 #minor 1.21.6-7 ready & Heads Update & GTB Themes Same Meaning Words and more to enjoy! (#107)
* Bump version from 5.0.15 to 5.0.15-SNAPSHOT0

* Fixed NPE AddGoBackButton

* Bump version from 5.0.15-SNAPSHOT0 to 5.0.15-SNAPSHOT1

* Fixed on Plotreset time did not update to world time

* Fixed Player Outside Plot interaction with blocks were possible

* Fixed Time.Changed message did not translate placeholder into language.yml content.

* Bump version from 5.0.15-SNAPSHOT1 to 5.0.15-SNAPSHOT2

* Fixed none builder Players of GTB didn't got the builder set weather and time

* Allow Plot selection also if ArenaState is FULL_GAME

* Fixed resetPlayerWeather did not change the weather

* Fixed clickable ground items due to new outside plot interaction check

* Fixed plot distribution on plot selection on a solo game could cause to set multiple players on the same plot

* Fixed plot distribution on plot selection on a solo game could cause to set multiple players on the same plot

* Added onVoteInventoryInteractEvent to block movement of items while plot voting stage.

* Fixed ItemFrames and Paintings were not able to be removed by player on plot.

* Bump version from 5.0.15-SNAPSHOT2 to 5.0.15-SNAPSHOT3

* Fixed on first time setup without restart the NPE getArenaInGameState is null

* Bump version from 5.0.15-SNAPSHOT3 to 5.0.15-SNAPSHOT4

* Fixed NPE if OptionsMenu Particles are opened as none builder whileas in gtb

* Bump version from 5.0.15-SNAPSHOT4 to 5.0.15-SNAPSHOT5

* Update MinigamesBox

* Bump version from 5.0.15-SNAPSHOT5 to 5.0.15-SNAPSHOT6

* Adjusted CHANGELOG.md

* Added a lot of new default themes at themes.yml

* Added possibility to add same meaning words for gtb themes by using ", " in themes.yml
Changed (for API usage) renamed BBTheme to GuessTheme

* Bump version from 5.0.15-SNAPSHOT6 to 5.0.15-SNAPSHOT7

* [ci skip] Adjusted CHANGELOG.md

* [ci skip] Update README.md

* Update README.md

* Bump version from 5.0.15-SNAPSHOT7 to 5.0.15-SNAPSHOT8

* Changed Heads menus from NormalInventory to Paginated Inventory to support more heads

* Bump version from 5.0.15-SNAPSHOT8 to 5.0.15-SNAPSHOT9

* [ci skip] Update README.md

* Updated MinigamesBox

* Bump version from 5.0.15-SNAPSHOT9 to 5.0.15-SNAPSHOT10

* Hide guessing players from builder in gtb mode

* Bump version from 5.0.15-SNAPSHOT10 to 5.0.15-SNAPSHOT11

* Fixed WaterFlow to Floor Ground

* Updated minigamesbox

* Bump version from 5.0.15-SNAPSHOT11 to 5.0.15-SNAPSHOT12

* Added Heads from HeadDatabase
Added /bba settheme <arena> <theme> for Console use
Fixed Floor NPC spawns on any actions

* Bump version from 5.0.15-SNAPSHOT12 to 5.0.15-SNAPSHOT13

* Fixed Vehicles such as Boats could drive outside plot
Fixed Flower Pots couldn't be destroyed on plot

* Bump version from 5.0.15-SNAPSHOT13 to 5.0.15-SNAPSHOT14

* Added LanguageMigrator

* Bump version from 5.0.15-SNAPSHOT14 to 5.0.15-SNAPSHOT15

* Fixed LanguageMigrator needed twice a boot. Added mainmenu.yml migrator.

* Fixed LanguageMigrator needed twice a boot. Added mainmenu.yml migrator.

* Added /bba forceplay <arena> <theme>

* Bump version from 5.0.15-SNAPSHOT15 to 5.0.15-SNAPSHOT16

* Fixed wrong game state if no players in arena on ForcePlayArgument use

* Bump version from 5.0.15-SNAPSHOT16 to 5.0.15-SNAPSHOT17

* Bump version from 5.0.15-SNAPSHOT17 to 5.0.15-SNAPSHOT18

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2025-07-14 23:20:29 +02:00
Tigerpanzer_02 2dc3e6a554 Revert " 1.21.6-7 ready & Heads Update & GTB Themes Same Meaning Words and mo…" (#106)
This reverts commit 2cdb2229ad.
2025-07-14 23:18:37 +02:00
Tigerpanzer_02andversion-bump[github-action] 2cdb2229ad 1.21.6-7 ready & Heads Update & GTB Themes Same Meaning Words and more to enjoy! (#105)
* Bump version from 5.0.15 to 5.0.15-SNAPSHOT0

* Fixed NPE AddGoBackButton

* Bump version from 5.0.15-SNAPSHOT0 to 5.0.15-SNAPSHOT1

* Fixed on Plotreset time did not update to world time

* Fixed Player Outside Plot interaction with blocks were possible

* Fixed Time.Changed message did not translate placeholder into language.yml content.

* Bump version from 5.0.15-SNAPSHOT1 to 5.0.15-SNAPSHOT2

* Fixed none builder Players of GTB didn't got the builder set weather and time

* Allow Plot selection also if ArenaState is FULL_GAME

* Fixed resetPlayerWeather did not change the weather

* Fixed clickable ground items due to new outside plot interaction check

* Fixed plot distribution on plot selection on a solo game could cause to set multiple players on the same plot

* Fixed plot distribution on plot selection on a solo game could cause to set multiple players on the same plot

* Added onVoteInventoryInteractEvent to block movement of items while plot voting stage.

* Fixed ItemFrames and Paintings were not able to be removed by player on plot.

* Bump version from 5.0.15-SNAPSHOT2 to 5.0.15-SNAPSHOT3

* Fixed on first time setup without restart the NPE getArenaInGameState is null

* Bump version from 5.0.15-SNAPSHOT3 to 5.0.15-SNAPSHOT4

* Fixed NPE if OptionsMenu Particles are opened as none builder whileas in gtb

* Bump version from 5.0.15-SNAPSHOT4 to 5.0.15-SNAPSHOT5

* Update MinigamesBox

* Bump version from 5.0.15-SNAPSHOT5 to 5.0.15-SNAPSHOT6

* Adjusted CHANGELOG.md

* Added a lot of new default themes at themes.yml

* Added possibility to add same meaning words for gtb themes by using ", " in themes.yml
Changed (for API usage) renamed BBTheme to GuessTheme

* Bump version from 5.0.15-SNAPSHOT6 to 5.0.15-SNAPSHOT7

* [ci skip] Adjusted CHANGELOG.md

* [ci skip] Update README.md

* Update README.md

* Bump version from 5.0.15-SNAPSHOT7 to 5.0.15-SNAPSHOT8

* Changed Heads menus from NormalInventory to Paginated Inventory to support more heads

* Bump version from 5.0.15-SNAPSHOT8 to 5.0.15-SNAPSHOT9

* [ci skip] Update README.md

* Updated MinigamesBox

* Bump version from 5.0.15-SNAPSHOT9 to 5.0.15-SNAPSHOT10

* Hide guessing players from builder in gtb mode

* Bump version from 5.0.15-SNAPSHOT10 to 5.0.15-SNAPSHOT11

* Fixed WaterFlow to Floor Ground

* Updated minigamesbox

* Bump version from 5.0.15-SNAPSHOT11 to 5.0.15-SNAPSHOT12

* Added Heads from HeadDatabase
Added /bba settheme <arena> <theme> for Console use
Fixed Floor NPC spawns on any actions

* Bump version from 5.0.15-SNAPSHOT12 to 5.0.15-SNAPSHOT13

* Fixed Vehicles such as Boats could drive outside plot
Fixed Flower Pots couldn't be destroyed on plot

* Bump version from 5.0.15-SNAPSHOT13 to 5.0.15-SNAPSHOT14

* Added LanguageMigrator

* Bump version from 5.0.15-SNAPSHOT14 to 5.0.15-SNAPSHOT15

* Fixed LanguageMigrator needed twice a boot. Added mainmenu.yml migrator.

* Fixed LanguageMigrator needed twice a boot. Added mainmenu.yml migrator.

* Added /bba forceplay <arena> <theme>

* Bump version from 5.0.15-SNAPSHOT15 to 5.0.15-SNAPSHOT16

* Fixed wrong game state if no players in arena on ForcePlayArgument use

* Bump version from 5.0.15-SNAPSHOT16 to 5.0.15-SNAPSHOT17

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2025-07-14 23:17:23 +02:00
version-bump[github-action] 1e53ce37cf Bump version from 5.0.14-SNAPSHOT8 to 5.0.15 2025-05-03 13:03:21 +00:00
Tigerpanzer_02andversion-bump[github-action] 34e28d3fef #patch Quality Of Life (QOL) Improvements (#104)
* Bump version from 5.0.14 to 5.0.14-SNAPSHOT0

* Allowing by default 20 places placeholder for summary list

* Bump version from 5.0.14-SNAPSHOT0 to 5.0.14-SNAPSHOT1

* Check every 10 seconds if OPTIONS_MENU item is still in builders inventory!

* Bump version from 5.0.14-SNAPSHOT1 to 5.0.14-SNAPSHOT2

* Ensure UTF-8 compiling

* Bump version from 5.0.14-SNAPSHOT2 to 5.0.14-SNAPSHOT3

* Fixed IllegalArgumentException on PlotSelector, also switched to PaginatedInventory to support all Plots

* Bump version from 5.0.14-SNAPSHOT3 to 5.0.14-SNAPSHOT4

* Added filter to maxplayers/random join team / solo so that only the correct arenas are selected

* Bump version from 5.0.14-SNAPSHOT4 to 5.0.14-SNAPSHOT5

* Updated Minigamesbox to 1.4.1

* Bump version from 5.0.14-SNAPSHOT5 to 5.0.14-SNAPSHOT6

* Adjusted CHANGELOG.md

* Bump version from 5.0.14-SNAPSHOT6 to 5.0.14-SNAPSHOT7

* Updated ParticlesOption Menu to use new Paginated Inventory

* Bump version from 5.0.14-SNAPSHOT7 to 5.0.14-SNAPSHOT8

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2025-05-03 15:03:02 +02:00
version-bump[github-action] 9e10545e5f Bump version from 5.0.13-SNAPSHOT10 to 5.0.14 2025-03-13 20:27:29 +00:00
Tigerpanzer_02andversion-bump[github-action] 17123e91db #patch Work with java8+ (#97)
* Bump version from 5.0.13 to 5.0.13-SNAPSHOT0

* Fixed NoSuchFieldError: Class org.bukkit.enchantments.Enchantment on some mc versions (e.g. 1.20)

* Bump version from 5.0.13-SNAPSHOT0 to 5.0.13-SNAPSHOT1

* Updated ScoreboardManager to match new ScoreboardApi

* Bump version from 5.0.13-SNAPSHOT1 to 5.0.13-SNAPSHOT2

* Updated ScoreboardManager to match new ScoreboardApi

* Bump version from 5.0.13-SNAPSHOT2 to 5.0.13-SNAPSHOT3

* Changed plot distribution on team mode tries to create only full plots now

Fixed plot distribution in same cases lets spectators into the plot as member
Fixed game ending due to not enough players counted spectators

* Bump version from 5.0.13-SNAPSHOT3 to 5.0.13-SNAPSHOT4

* Moved from gradle to maven to support java 8 language level again

* Bump version from 5.0.13-SNAPSHOT4 to 5.0.13-SNAPSHOT5

* Moved from gradle to maven to support java 8 language level again

* Bump version from 5.0.13-SNAPSHOT5 to 5.0.13-SNAPSHOT6

* Update citiziens repo

* Bump version from 5.0.13-SNAPSHOT6 to 5.0.13-SNAPSHOT7

* MinimizeJar

* Bump version from 5.0.13-SNAPSHOT7 to 5.0.13-SNAPSHOT8

* Fixed ${description} invalid

* Bump version from 5.0.13-SNAPSHOT8 to 5.0.13-SNAPSHOT9

* Updated CHANGELOG.md

* Bump version from 5.0.13-SNAPSHOT9 to 5.0.13-SNAPSHOT10

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2025-03-13 21:27:05 +01:00
version-bump[github-action] ca42285076 Bump version from 5.0.12-SNAPSHOT1 to 5.0.13 2025-02-18 19:38:40 +00:00
Tigerpanzer_02andversion-bump[github-action] b2dbb5adaf #patch Fixed Progress must be between 0 and 1 (#96)
* Bump version from 5.0.12 to 5.0.12-SNAPSHOT0

* Fixed Progress must be between 0 and 1

* Bump version from 5.0.12-SNAPSHOT0 to 5.0.12-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2025-02-18 20:37:52 +01:00
version-bump[github-action] 67f27359e8 Bump version from 5.0.11-SNAPSHOT4 to 5.0.12 2025-02-17 21:23:55 +00:00
Tigerpanzer_02andversion-bump[github-action] 6ff5236241 #patch Back to stability 2.0 (#95)
* Bump version from 5.0.11 to 5.0.11-SNAPSHOT0

* Fixed a bug on gtb where players were getting points for guess even when they wrote the theme on chat when it was already shown by the plugin

* Updated config to match core version 5

* Fixed block destroy drops

* Fixed gtb Arena CleanUp which results in first round issues at selection of theme etc.

* Fixed gtb options menu is not showing up for every builder

* Fixed gtb plot reset

* Bump version from 5.0.11-SNAPSHOT0 to 5.0.11-SNAPSHOT1

* Updated MiniGamesBox

* Bump version from 5.0.11-SNAPSHOT1 to 5.0.11-SNAPSHOT2

* Fixed ItemSpawn on Plotarea also for dropped items by not player related drops

* Bump version from 5.0.11-SNAPSHOT2 to 5.0.11-SNAPSHOT3

* Fixed players are collidable on normal made

* Updated CHANGELOG.md

* Updated CHANGELOG.md

* Bump version from 5.0.11-SNAPSHOT3 to 5.0.11-SNAPSHOT4

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2025-02-17 22:23:08 +01:00
Tigerpanzer_02 7d0157a3ce Update deploy-master.yml 2025-02-12 19:13:48 +01:00
Tigerpanzer_02 c5b204f12d Update deploy-development.yml 2025-02-12 19:13:17 +01:00
Tigerpanzer_02 e7303d7b5d Fixed spectator counts on gtb guess 2025-01-27 23:17:35 +01:00
Tigerpanzer_02 3b6871bdfb Fixed bba settheme not working, now works
if executed in lobby: skip voting when game starts
and allow executing it all the time after game started so admin can change theme anytime
2025-01-27 23:14:33 +01:00
Tigerpanzer_02 4a00729153 Misc changed stained glass pane naming to ??? 2025-01-27 22:27:29 +01:00
Tigerpanzer_02 acc6d9bea4 Fixed PlayerHeads on 1.20+ 2025-01-27 22:26:58 +01:00
Tigerpanzer_02 8dc6ece9f7 Fixed clearing of dropped items on 1.21+ 2025-01-27 22:26:24 +01:00
Tigerpanzer_02 52013964be Added notice for Mob.Spawn that it also contains Armour Stands 2025-01-27 22:24:24 +01:00
Tigerpanzer_02 1566119559 Updated Gradle 2025-01-27 22:24:06 +01:00
Tigerpanzer_02 c1bdf92925 Fixed Biomes on 1.21 2025-01-27 22:23:34 +01:00
Tigerpanzer_02 588e6fb0f3 Fixed Banner Building on 1.20+ 2025-01-27 22:23:16 +01:00
Tigerpanzer_02 4257e7ba53 Fixed Creature Spawning outside plots in same world 2025-01-27 22:12:57 +01:00
version-bump[github-action] 4305660bff Bump version from 5.0.10-SNAPSHOT1 to 5.0.11 2024-07-12 23:49:14 +00:00
Tigerpanzer_02andversion-bump[github-action] 2beeb74559 #patch Fixed 1.20.6 & 1.21 (#89)
* Bump version from 5.0.10 to 5.0.10-SNAPSHOT0

* Changed ServerVersion as 1.20.6+ removed package nms

* Bump version from 5.0.10-SNAPSHOT0 to 5.0.10-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2024-07-13 01:48:22 +02:00
version-bump[github-action] 66e556003e Bump version from 5.0.9-SNAPSHOT1 to 5.0.10 2024-07-10 23:15:17 +00:00
Tigerpanzer_02andversion-bump[github-action] a3e590ce07 #patch Fixed a plugin crash on none paperspigot software servers (#88)
* Bump version from 5.0.9 to 5.0.9-SNAPSHOT0

* Updated to minigamesbox 1.3.12

* Bump version from 5.0.9-SNAPSHOT0 to 5.0.9-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2024-07-11 01:14:21 +02:00
version-bump[github-action] a81d21d4ec Bump version from 5.0.8-SNAPSHOT2 to 5.0.9 2024-07-09 20:13:37 +00:00
bc575c26d2 #patch Fixed several issues (#87)
Special thanks to https://github.com/Waterman1001

* Bump version from 5.0.7-SNAPSHOT1 to 5.0.8

* Fixed many bugs in BuildBattle plugin (#86)

* Updated plugin.yml to prevent invalid file error on startup

* Changed version of dependency MiniGamesBox to circumvent build issues

* Fixed error in time change menu

* Fixed issue with %player% placeholder (should be lowercase)

* Bump version from 5.0.7-SNAPSHOT1 to 5.0.8

* Fixed problem in place rewards

* Cancelled BlockExplodeEvent to prevent blocks such as Respawn Anchor explode and damage the arena.

* Fixed BuildBattle menu item not working because API was used at 2 different places. Added bb menu command and used registerSpecialItem to fix.

* Disabled enderpearl throwing while in arena because it allows to teleport to other players plots or outside the arena map, even during voting stage.

* Changed back version number of MiniGamesBox to 1.3.10

* Fixed small error if non-player threw projectile.

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>

* Bump version from 5.0.8 to 5.0.8-SNAPSHOT0

* fix: fixed ChunkManager.sendMapChunk

* Bump version from 5.0.8-SNAPSHOT0 to 5.0.8-SNAPSHOT1

* Updated to minigamesbox 1.3.11

* Bump version from 5.0.8-SNAPSHOT1 to 5.0.8-SNAPSHOT2

* Update CHANGELOG.md

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
Co-authored-by: Onno <emailodg@gmail.com>
Co-authored-by: Lagggpixel <lagggpixel@gmail.com>
2024-07-09 22:12:43 +02:00
version-bump[github-action] 4fb500c015 Bump version from 5.0.7-SNAPSHOT1 to 5.0.8 2024-06-24 09:18:23 +00:00
Wanbin Caoandversion-bump[github-action] 86202128d2 #patch bumped minigames box version (#85)
* Bump version from 5.0.7 to 5.0.7-SNAPSHOT0

* feat: bumped minigames box version

* Bump version from 5.0.7-SNAPSHOT0 to 5.0.7-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2024-06-24 10:17:07 +01:00
version-bump[github-action] 83fc1a5904 Bump version from 5.0.6-SNAPSHOT1 to 5.0.7 2024-06-21 16:10:21 +00:00
Wanbin Caoandversion-bump[github-action] ecc34b0816 #patch API update and minor improvements (#84)
* Bump version from 5.0.6 to 5.0.6-SNAPSHOT0

* feat: added new API compatibility

* feat: optimised scoreboard

* feat: added allowing disabling of super votes
https://github.com/Sowgro

* Bump version from 5.0.6-SNAPSHOT0 to 5.0.6-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2024-06-21 17:09:17 +01:00
version-bump[github-action] 980defa641 Bump version from 5.0.5-SNAPSHOT1 to 5.0.6 2024-04-23 23:23:03 +00:00
Tigerpanzer_02andversion-bump[github-action] ddbc20a599 #patch General optimization (#81)
* Bump version from 5.0.5 to 5.0.5-SNAPSHOT0

* Updated to minigamesbox 1.3.8

* Bump version from 5.0.5-SNAPSHOT0 to 5.0.5-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2024-04-24 01:21:49 +02:00
version-bump[github-action] b79439d225 Bump version from 5.0.4-SNAPSHOT2 to 5.0.5 2024-01-15 22:36:58 +00:00
Tigerpanzer_02andversion-bump[github-action] e3a69aca1b #patch Minigamesbox 1.3.7 (#80)
* Bump version from 5.0.4 to 5.0.4-SNAPSHOT0

* Fetched latest changes from minigamesbox

* Bump version from 5.0.4-SNAPSHOT0 to 5.0.4-SNAPSHOT1

* Updated to minigamesbox 1.3.7

* Bump version from 5.0.4-SNAPSHOT1 to 5.0.4-SNAPSHOT2

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2024-01-15 23:36:06 +01:00
version-bump[github-action] 9ca6a7b364 Bump version from 5.0.3-SNAPSHOT1 to 5.0.4 2024-01-13 01:38:53 +00:00
Tigerpanzer_02andversion-bump[github-action] b99e2ee4db #patch General improvements / code maintenance (#79)
* Bump version from 5.0.3 to 5.0.3-SNAPSHOT0

* Fetched minigamesbox 1.3.6

* Bump version from 5.0.3-SNAPSHOT0 to 5.0.3-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2024-01-13 02:37:59 +01:00
version-bump[github-action] 1ebedf3741 Bump version from 5.0.2-SNAPSHOT1 to 5.0.3 2024-01-03 00:02:28 +00:00
Tigerpanzer_02andversion-bump[github-action] 19cc22aca6 #patch Fixed startup issues (#78)
* Bump version from 5.0.2 to 5.0.2-SNAPSHOT0

* Fetched 1.3.5 MiniGamesBox

* Bump version from 5.0.2-SNAPSHOT0 to 5.0.2-SNAPSHOT1

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
2024-01-03 01:01:35 +01:00
version-bump[github-action] 98dee905f4 Bump version from 5.0.1-SNAPSHOT5 to 5.0.2 2023-12-31 14:41:18 +00:00
0d10f65a45 #patch Added 1.20.3 & 4 (#77)
* Bump version from 5.0.0 to 5.0.0-SNAPSHOT0

* Added CHANGELOG.md

* Fixed gtb round reset on player leave

* Bump version from 5.0.0-SNAPSHOT0 to 5.0.0-SNAPSHOT1

* Fixed bouncing and mouse pointer reset on themevoting

* Bump version from 5.0.0-SNAPSHOT1 to 5.0.0-SNAPSHOT2

* Fetched minigamesbox 1.3.4

* Bump version from 5.0.0-SNAPSHOT2 to 5.0.0-SNAPSHOT3

* Fetched minigamescore changes
Corrected version number

* Corrected version number

* Bump version from 5.0.1-SNAPSHOT4 to 5.0.1-SNAPSHOT5

---------

Co-authored-by: version-bump[github-action] <41898282+version-bump[github-action]@users.noreply.github.com>
Co-authored-by: Tigerpanzer_02 <plugilyprojects@gmail.com>
2023-12-31 15:40:24 +01:00
version-bump[github-action] 76e3002246 Bump version from 4.5.2-SNAPSHOT98 to 5.0.0 2023-08-09 19:12:55 +00:00
Tigerpanzer_02 b34a7c177f #major Merge pull request #76 from Plugily-Projects/development
5.0.0 Release
2023-08-09 21:11:45 +02:00
version-bump[github-action] 02fbca16ed Bump version from 4.5.2-SNAPSHOT97 to 4.5.2-SNAPSHOT98 2023-08-09 19:00:07 +00:00
Tigerpanzer_02 9e4545e923 Added default maven pom 2023-08-09 20:58:33 +02:00
Tigerpanzer_02 60b43e1def Moved locales to remote 2023-08-09 20:26:58 +02:00
Tigerpanzer_02 59c7313a78 Merge remote-tracking branch 'origin/development' into development 2023-08-03 00:10:57 +02:00
Tigerpanzer_02 175d1391f4 update config.yml 2023-06-07 22:15:31 +02:00
version-bump[github-action] 014c7a8ba2 Bump version from 4.5.2-SNAPSHOT96 to 4.5.2-SNAPSHOT97 2023-06-07 17:48:43 +00:00
Tigerpanzer_02 e0992658f6 Merge remote-tracking branch 'origin/development' into development 2023-06-07 18:48:10 +02:00
Tigerpanzer_02 287ca3701c Added persian 2023-06-07 18:43:38 +02:00
version-bump[github-action] e8ae19af90 Bump version from 4.5.2-SNAPSHOT95 to 4.5.2-SNAPSHOT96 2023-06-06 20:00:05 +00:00
Tigerpanzer_02 86999c0e2a Updated translations 2023-06-06 21:59:04 +02:00
version-bump[github-action] 099f469df4 Bump version from 4.5.2-SNAPSHOT94 to 4.5.2-SNAPSHOT95 2023-05-04 22:02:48 +00:00
Tigerpanzer_02 5711dfaf44 added todo 2023-05-05 00:00:52 +02:00
Tigerpanzer_02 6c8cb2604a Fixed GTB +points 2023-05-04 23:54:54 +02:00
Tigerpanzer_02 636cfacd4f Fixed GTB Solo Mode 2023-05-04 23:46:38 +02:00
Tigerpanzer_02 c0a667b50a Merge remote-tracking branch 'origin/development' into development 2023-05-04 22:19:53 +02:00
Tigerpanzer_02 f2fcdcfe6f fixed difficulty_points_reward placeholder 2023-05-04 22:19:19 +02:00
version-bump[github-action] b5d768300f Bump version from 4.5.2-SNAPSHOT93 to 4.5.2-SNAPSHOT94 2023-05-04 19:16:12 +00:00
Tigerpanzer_02 2480f749a1 update minigamesbox 2023-05-04 21:10:11 +02:00
Tigerpanzer_02 0367a0a47a Change Teammode vote points to be per plot 2023-05-04 21:08:49 +02:00
Tigerpanzer_02 dc0f2b2dc8 Fixed teleport and creative mode on plot move 2023-05-04 21:07:47 +02:00
Tigerpanzer_02 94b6ff76f6 Fixed & Moved teammates placeholder on scoreboard 2023-05-04 21:07:10 +02:00
Tigerpanzer_02 dd58e1a6d9 Checking for min players on classic team mode 2023-05-04 19:52:45 +02:00
Tigerpanzer_02 4d6ffe3e51 Adjusted permissions from heads & particles 2023-05-04 19:27:54 +02:00
Tigerpanzer_02 f9bcf3c40f Adjusted permissions from heads & particles 2023-05-04 19:16:47 +02:00
version-bump[github-action] 35b3954611 Bump version from 4.5.2-SNAPSHOT92 to 4.5.2-SNAPSHOT93 2023-05-04 17:10:03 +00:00
Tigerpanzer_02 a18edc2e6c update minigamesbox 2023-05-04 19:08:51 +02:00
Tigerpanzer_02 563d558279 Fixed theme reset on arena restart 2023-05-04 18:37:49 +02:00
Tigerpanzer_02 add74a6406 Misc menuitem cleanup 2023-05-04 18:37:26 +02:00
Tigerpanzer_02 9b92b75937 Fixed forcestopped game end message 2023-05-04 18:26:13 +02:00
Tigerpanzer_02 f5ed87a9d2 Fixed OptionsRegistry 2023-05-04 18:25:15 +02:00
Tigerpanzer_02 4251a3b620 Fixed banner base color on 1.12+ 2023-05-04 18:24:34 +02:00
Tigerpanzer_02 cac21e38b4 Moved MenuOptions to new Inventories from MinigamesBox 2023-05-04 13:10:58 +02:00
Tigerpanzer_02 9d877e4cf1 Adjust messages to match new design 2023-05-04 10:54:57 +02:00
version-bump[github-action] de32e96ccc Bump version from 4.5.2-SNAPSHOT91 to 4.5.2-SNAPSHOT92 2023-05-02 18:59:40 +00:00
Tigerpanzer_02 02257d82fc moved to gradle.kts and updated dependencies 2023-05-02 20:59:40 +02:00
version-bump[github-action] eee9d6d243 Bump version from 4.5.2-SNAPSHOT90 to 4.5.2-SNAPSHOT91 2023-04-03 19:59:25 +00:00
Tigerpanzer_02 e4282b6e5a fixed winner plot is wrong position 2023-04-03 21:59:24 +02:00
version-bump[github-action] e1b3096e68 Bump version from 4.5.2-SNAPSHOT89 to 4.5.2-SNAPSHOT90 2023-02-27 22:20:39 +00:00
Tigerpanzer_02 3ba4c6e826 simplify toplist calculation on all modes 2023-02-27 23:19:54 +01:00
Tigerpanzer_02 3da9c7de28 Fixed difficulty_points_reward placeholder naming
Fixed Guess.Points message throws raw placeholder
2023-02-27 21:06:43 +01:00
version-bump[github-action] 3c01d696b5 Bump version from 4.5.2-SNAPSHOT88 to 4.5.2-SNAPSHOT89 2023-02-26 21:00:27 +00:00
Tigerpanzer_02 8934363931 Fixed theme placeholders and actionbar on gtb mode 2023-02-26 21:59:47 +01:00
Tigerpanzer_02 38bcf87c97 Added vote name in message 2023-02-25 18:39:23 +01:00
Tigerpanzer_02 770772ce77 Fixed weather change message 2023-02-25 18:34:40 +01:00
Tigerpanzer_02 cb53f59af7 [ci skip] Updated README.md 2022-12-30 21:24:19 +01:00
version-bump[github-action] 4d0673acd6 Bump version from 4.5.2-SNAPSHOT87 to 4.5.2-SNAPSHOT88 2022-12-30 20:23:16 +00:00
Tigerpanzer_02 bffeacc7ad Update README.md 2022-12-30 21:22:35 +01:00
version-bump[github-action] 62d19c4a80 Bump version from 4.5.2-SNAPSHOT86 to 4.5.2-SNAPSHOT87 2022-12-30 14:46:01 +00:00
Tigerpanzer_02 3b82c54d11 Merge remote-tracking branch 'origin/development' into development 2022-12-30 15:45:19 +01:00
Tigerpanzer_02 446f2cd58b just build 2022-12-30 15:45:13 +01:00
version-bump[github-action] fd6a162b22 Bump version from 4.5.2-SNAPSHOT85 to 4.5.2-SNAPSHOT86 2022-12-30 13:27:02 +00:00
Tigerpanzer_02 c8e4b9a55f Merge remote-tracking branch 'origin/development' into development 2022-12-30 14:26:16 +01:00
Tigerpanzer_02 d5dba852d0 setting javaToolchains 2022-12-30 14:26:10 +01:00
version-bump[github-action] 7fd7e81d51 Bump version from 4.5.2-SNAPSHOT84 to 4.5.2-SNAPSHOT85 2022-12-29 10:33:28 +00:00
Tigerpanzer_02 34f7e8fa5e Merge remote-tracking branch 'origin/development' into development 2022-12-29 11:32:45 +01:00
Tigerpanzer_02 e7ef99f034 setting java compatibility 2022-12-29 11:32:34 +01:00
version-bump[github-action] 8c34dd6f00 Bump version from 4.5.2-SNAPSHOT83 to 4.5.2-SNAPSHOT84 2022-12-29 10:11:34 +00:00
Tigerpanzer_02 5f93749a14 Merge remote-tracking branch 'origin/development' into development 2022-12-29 11:10:45 +01:00
Tigerpanzer_02 e25712678f setting java compatibility 2022-12-29 11:10:37 +01:00
version-bump[github-action] 764ba1208b Bump version from 4.5.2-SNAPSHOT82 to 4.5.2-SNAPSHOT83 2022-12-29 09:22:00 +00:00
Tigerpanzer_02 fabdb348f1 setting java compatibility 2022-12-29 10:21:11 +01:00
version-bump[github-action] 9bb872d280 Bump version from 4.5.2-SNAPSHOT81 to 4.5.2-SNAPSHOT82 2022-12-28 23:03:08 +00:00
Tigerpanzer_02 0c3855be55 Merge remote-tracking branch 'origin/development' into development 2022-12-29 00:02:29 +01:00
Tigerpanzer_02 29436a34b0 simplify publications 2022-12-29 00:02:21 +01:00
version-bump[github-action] 5cad070ace Bump version from 4.5.2-SNAPSHOT80 to 4.5.2-SNAPSHOT81 2022-12-28 22:56:13 +00:00
Tigerpanzer_02 e05856d225 Updated implementation 2022-12-28 23:55:38 +01:00
version-bump[github-action] 09d698a634 Bump version from 4.5.2-SNAPSHOT79 to 4.5.2-SNAPSHOT80 2022-12-28 18:38:36 +00:00
Tigerpanzer_02 f9087e1b3c Merge remote-tracking branch 'origin/development' into development 2022-12-28 19:37:54 +01:00
Tigerpanzer_02 55611ef5d0 Moved from maven to gradle 2022-12-28 19:37:46 +01:00
version-bump[github-action] 0652138f30 Bump version from 4.5.2-SNAPSHOT78 to 4.5.2-SNAPSHOT79 2022-12-28 18:35:47 +00:00
Tigerpanzer_02 e3f558cefd Moved from maven to gradle 2022-12-28 19:35:06 +01:00
Tigerpanzer02 f21aaec4f3 Bump pom.xml from 4.5.2-dev77 to 4.5.2-dev78 2022-11-10 21:12:34 +00:00
Onno a507fcfebe Updated default floor material config string as the old one was not working (#74) 2022-11-10 22:12:00 +01:00
Tigerpanzer02 8a2cc43945 Bump pom.xml from 4.5.2-dev76-debug to 4.5.2-dev77 2022-11-01 22:28:37 +00:00
Tigerpanzer_02 0e461298fe PlotMenu gui size wasn't increased 2022-11-01 23:25:57 +01:00
Tigerpanzer_02 77370fa524 Optimize plot members printing at plot voting state 2022-11-01 23:24:44 +01:00
Tigerpanzer_02 347e858c3e Added team mode for GTB
Changed GTB just needs 1 plot now
2022-11-01 23:23:24 +01:00
Tigerpanzer_02 9749c3568e Added gtb_rounds placeholder
Fixed language.yml placeholders
2022-11-01 13:26:45 +01:00
Tigerpanzer_02 7759b45278 Added custom rounds for gtb GTB_ROUNDS_PER_PLOT 2022-10-31 16:10:02 +01:00
Tigerpanzer_02 db4f2b08d0 Added init debug for arenatype 2022-10-29 10:36:25 +02:00
Tigerpanzer_02 efd0d3e541 Fixed placeholders for gtb scoreboard 2022-10-29 10:35:57 +02:00
Tigerpanzer_02 00dbe11c02 Fixed placeholder not found issues 2022-10-29 10:35:44 +02:00
Tigerpanzer_02 8b6186c509 Merge remote-tracking branch 'origin/development' into development 2022-10-29 09:49:40 +02:00
Tigerpanzer_02 35c6f0a7a4 Fixed ArenaRegistry.getNewArena did only get classic arenas 2022-10-29 09:43:39 +02:00
Tigerpanzer02 09af443311 Bump pom.xml from 4.5.2-dev76 to 4.5.2-dev77 2022-10-29 07:06:17 +00:00
montlikadani 15777bf035 Reduce the private methods (boot package) being created when compiling the resource (#69)
* Reduce the private methods from being created when compiling
2022-10-29 09:05:38 +02:00
Tigerpanzer02 7e4359b3b9 Bump pom.xml from 4.5.2-dev75 to 4.5.2-dev76 2022-10-24 20:16:51 +00:00
Tigerpanzer_02 015b296822 Fixed broken setup menu because startlocation key name was missing 2022-10-24 22:16:17 +02:00
Tigerpanzer02 bbb19e761b Bump pom.xml from 4.5.2-dev74 to 4.5.2-dev75 2022-10-24 14:53:39 +00:00
Tigerpanzer_02 0bb8cabf03 Merge remote-tracking branch 'origin/development' into development 2022-10-24 16:52:56 +02:00
Tigerpanzer_02 d5fafe0433 Fixed PLOT_HIDE_OWNER config path 2022-10-24 16:52:39 +02:00
Tigerpanzer02 fe9e92d5c9 Bump pom.xml from 4.5.2-dev73 to 4.5.2-dev74 2022-10-24 14:51:13 +00:00
Tigerpanzer_02 5b945dde87 Moved Allow-Players-Moving-Outside-Of-Arena to configoption PLOT_MOVE_OUTSIDE 2022-10-24 16:50:19 +02:00
Tigerpanzer02 cee8ce1b4d Bump pom.xml from 4.5.2-dev72 to 4.5.2-dev73 2022-10-24 14:31:30 +00:00
Tigerpanzer_02 7f4e22f60d Merge pull request #70 from montlikadani/option-to-allow-moving-outside-arena
Add option to allow players moving outside of arena
2022-10-24 16:30:46 +02:00
montlikadani 98ec0e7ac7 Add option to allow players moving outside of arena 2022-10-24 16:21:22 +02:00
Tigerpanzer02 d9c9801d71 Bump pom.xml from 4.5.2-dev71 to 4.5.2-dev72 2022-10-18 21:10:18 +00:00
Tigerpanzer_02 3544afd337 Fixed player votes where possible without voteitem in hand 2022-10-18 23:09:32 +02:00
Tigerpanzer_02 a9335aef33 Fixed placeholder infinite loop at game summary 2022-10-18 23:09:07 +02:00
Tigerpanzer02 7bba49e59e Bump pom.xml from 4.5.2-dev70 to 4.5.2-dev71 2022-10-16 13:26:16 +00:00
Tigerpanzer_02 13b545ae1d Merge remote-tracking branch 'origin/development' into development 2022-10-16 15:25:24 +02:00
Tigerpanzer_02 fb6d20a5c9 Fixed arena_summary_place_list placeholder 2022-10-16 15:25:12 +02:00
Tigerpanzer_02 8177c5fd23 Delete the empyt char at the end on arena_place_member_x placeholder 2022-10-16 12:38:35 +02:00
Tigerpanzer_02 c7efff3771 Updated Copyright 2022-10-16 12:21:11 +02:00
Tigerpanzer_02 4bf9d51c0e Renamed ArenaInGameStage to ArenaInGameState 2022-10-16 12:17:22 +02:00
Tigerpanzer_02 850add20ec Added ArenaIngameStage NONE 2022-10-16 12:13:07 +02:00
Tigerpanzer_02 beed101d57 Fixed VoteMenu reset on multiple arena starts 2022-10-16 12:12:23 +02:00
Tigerpanzer02 72243203cb Bump pom.xml from 4.5.2-dev69 to 4.5.2-dev70 2022-10-15 22:04:10 +00:00
Tigerpanzer_02 a7b42f4fbd Removed public abuse from boot 2022-10-16 00:03:42 +02:00
Tigerpanzer02 141d5dfc59 Bump pom.xml from 4.5.2-dev68 to 4.5.2-dev69 2022-10-15 21:57:46 +00:00
Tigerpanzer_02 7fdb9cdadd Merge remote-tracking branch 'origin/development' into development 2022-10-15 23:57:24 +02:00
Tigerpanzer_02 3b869179a1 Splitting Main into boot classes 2022-10-15 23:57:14 +02:00
Tigerpanzer02 72f54694a5 Bump pom.xml from 4.5.2-dev67-debug to 4.5.2-dev68 2022-10-15 21:22:00 +00:00
Tigerpanzer_02 98fa4fc87f Fixed summary placeholders 2022-10-15 23:21:20 +02:00
Tigerpanzer02 7d5fed68fc Bump pom.xml from 4.5.2-dev66 to 4.5.2-dev67 2022-10-14 04:38:01 +00:00
Tigerpanzer_02 ff8df2225f Merge pull request #67 from montlikadani/fix-voting-phase
Fix when in the voting phase, there were more voting stages than players count
2022-10-14 06:37:32 +02:00
montlikadani 1b54874421 Fix when in the voting phase, there were more voting stages than players count 2022-10-13 17:02:39 +02:00
Tigerpanzer02 dce6552783 Bump pom.xml from 4.5.2-dev65 to 4.5.2-dev66 2022-09-24 09:24:06 +00:00
Tigerpanzer_02 69068779ea Merge pull request #66 from montlikadani/fix-reports-statistic-type
Rename user statistics reports to reports_triggered
2022-09-24 11:23:30 +02:00
montlikadani f357b85162 Rename user statistics reports to reports_triggered 2022-09-24 11:19:22 +02:00
Tigerpanzer02 f115a355d9 Bump pom.xml from 4.5.2-dev64 to 4.5.2-dev65 2022-09-21 22:45:04 +00:00
Tigerpanzer_02 d5b0923a95 Fixed VoteMenu 2022-09-22 00:44:18 +02:00
Tigerpanzer_02 d981df9b37 Fixed theme is not set after theme selection 2022-09-22 00:28:47 +02:00
Tigerpanzer02 ce9a1a4806 Bump pom.xml from 4.5.2-dev63 to 4.5.2-dev64 2022-09-21 18:42:12 +00:00
Tigerpanzer_02 de71f904c9 Removed unused event 2022-09-21 20:41:14 +02:00
version-bump[github-action] f150a0808c Bump pom.xml from 4.5.2-dev62 to 4.5.2-dev63 2022-09-21 18:11:21 +00:00
Tigerpanzer_02 8e11c3423a Fixed pom version 2022-09-21 20:10:44 +02:00
version-bump[github-action] 7fe6c5ba39 Bump pom.xml from 4.5.2-dev62 to - 2022-09-21 18:03:15 +00:00
Tigerpanzer_02 dc81cb6702 Fixed BannerMenu and ParticleMenu not fully opened 2022-09-20 22:30:14 +02:00
Tigerpanzer_02 ffece8e69d Fixed STATISTIC names 2022-09-20 22:29:46 +02:00
github-actions[bot] 3737a8f77b Bump pom.xml from 4.5.2-dev61 to 4.5.2-dev62 2022-09-19 18:02:14 +00:00
montlikadani e44c2caf29 Fixed NPE when calculating plot results (#63)
...and the voting plot did not set
2022-09-19 20:01:41 +02:00
montlikadani 99947579ba Fixed banner menu can not be opened (#62)
* Fix banner menu not opened

* Apply the suggestions
2022-09-19 20:01:10 +02:00
github-actions[bot] dea9cc876e Bump pom.xml from 4.5.2-dev60 to 4.5.2-dev61 2022-09-19 17:54:38 +00:00
montlikadani dff17c85ad Fixed time change option did not worked after the menu closed (#64)
* Fixed time change option did not worked after the menu closed

Also fixed wrong message was sent to player when changing weather type

* Apply the suggestions
2022-09-19 19:54:13 +02:00
github-actions[bot] 729e0fd925 Bump pom.xml from 4.5.2-dev59 to 4.5.2-dev60 2022-09-19 17:49:57 +00:00
Tigerpanzer_02 075489628e Merge pull request #65 from montlikadani/improve-particle-scheduler
Improve particle refreshing scheduler
2022-09-19 19:49:30 +02:00
montlikadani 1145c3e1f3 Apply the suggestions 2022-09-19 15:17:22 +02:00
montlikadani 6f15842f89 Improve particle refreshing scheduler 2022-09-17 18:50:43 +02:00
github-actions[bot] b40be6d908 Bump pom.xml from 4.5.2-dev58 to 4.5.2-dev59 2022-09-16 21:03:11 +00:00
Tigerpanzer_02 d9598aba9b Fixed plot time change message 2022-09-16 23:02:40 +02:00
Tigerpanzer_02 b61d989b28 Fixed sonar issue about doubled code 2022-09-16 22:45:48 +02:00
Tigerpanzer_02 7ddfff7886 Fixed arena stops if enough players are ingame 2022-09-16 22:41:21 +02:00
Tigerpanzer_02 09a7e8b954 Fixed VoteMenu does not close on failed arena start 2022-09-16 22:40:48 +02:00
Tigerpanzer_02 64ae0540b1 Fixed VoteMenu placeholders 2022-09-16 22:35:46 +02:00
Tigerpanzer_02 18fd40a294 Fixed PlotMenu messages 2022-09-16 22:23:36 +02:00
Tigerpanzer_02 624e0d4bab Disabling SERVER_JOIN items on special_items.yml by default 2022-09-16 22:09:52 +02:00
Tigerpanzer_02 69af87153c Fixed plotselector item does not have the command on special_items.yml 2022-09-16 22:08:36 +02:00
github-actions[bot] 524cc7ff51 Bump pom.xml from 4.5.2-dev57 to 4.5.2-dev58 2022-09-16 20:07:44 +00:00
Tigerpanzer_02 2b52314b89 Merge pull request #61 from montlikadani/fix-particles-in-menu
Fixed when there was no particles added in the menu
2022-09-16 22:07:17 +02:00
montlikadani a3bc95ec7b Fixed when there was no particles added in the menu 2022-09-08 19:51:08 +02:00
github-actions[bot] 66f4e65187 Bump pom.xml from 4.5.2-dev56 to 4.5.2-dev57 2022-09-05 17:20:22 +00:00
Tigerpanzer_02 ec55d4db84 Merge pull request #60 from montlikadani/remove-useless-additem-from-plotmenu
Removed useless addItem from plotMenuHandler
2022-09-05 19:19:55 +02:00
montlikadani 860fda414e Removed useless addItem from plotMenuHandler 2022-09-04 19:19:04 +02:00
github-actions[bot] 5ba4431d8a Bump pom.xml from 4.5.2-dev55 to 4.5.2-dev56 2022-09-02 21:34:29 +00:00
Tigerpanzer_02 cb5e5e431f Update setup menu 2022-09-02 23:33:56 +02:00
Tigerpanzer_02 2f07f5f3f0 Change Scoreboard arena naming from basearena to arena 2022-08-31 22:51:47 +02:00
github-actions[bot] eba7912e39 Bump pom.xml from 4.5.2-dev54 to 4.5.2-dev55 2022-08-29 18:48:16 +00:00
montlikadaniandTigerpanzer_02 9d712b2530 Use World#refreshChunk to refresh chunks and biomes at given locations (#54)
supports 1.18 and 1.19 and hopefully newer versions!

Log:
* Fix parameter for ClientboundLevelChunkPacketData constructor?

* Fixed changing biomes in plots did not worked

We don't need anymore NMS it is enough if we do World#refreshChunk and the biome changes in specific locations.

* Make sure to perform this refresh chunk in Paper

* Seems this works on Spigot

* Also do this for default plot biome

* Change version for refreshing chunks to 1.15

Co-authored-by: Tigerpanzer_02 <37453987+Tigerpanzer02@users.noreply.github.com>
2022-08-29 20:47:46 +02:00
github-actions[bot] 38555bc401 Bump pom.xml from 4.5.2-dev53 to 4.5.2-dev54 2022-08-24 09:11:27 +00:00
montlikadani d771564fff Fixed a bunch of issues (read desc) (#59)
-Another StackOverflowError for VoteMenu close event, now it seems to work now
-Removed the pickup event to allow for players to pickup items from the ground while in an arena (because why not, they can't do anything wrong I guess)
-Updated Paper api to 1.19.2
-Fixed text duplications for VoteMenu items, we need to deep copy those items to avoid overriding
-Fixed when players can not build in arena after vote phase
-Improved the inventory checking in OptionsMenu, so the options inventory is now cached
-Now changing floor by clicking on the Villager works

Commits:
* Improvements

* Use runTask to open vote menu inventory on next server tick

* Fixed changing floor using villager did not worked
2022-08-24 11:10:57 +02:00
github-actions[bot] 0b6ddb6192 Bump pom.xml from 4.5.2-dev52 to 4.5.2-dev53 2022-08-12 21:12:20 +00:00
Tigerpanzer_02 509822388d Fixed arena is getting stopped after starting 2022-08-12 23:11:48 +02:00
github-actions[bot] 8b007371dc Bump pom.xml from 4.5.2-dev51 to 4.5.2-dev52 2022-08-12 19:56:18 +00:00
montlikadani 03fcb889ff Fixed stackoverflow error during vote time (#57) 2022-08-12 21:55:47 +02:00
github-actions[bot] 4903ed6333 Bump pom.xml from 4.5.2-dev50 to 4.5.2-dev51 2022-08-11 20:34:48 +00:00
Tigerpanzer_02 bf4438547a Renamed BuildArena.setArenaType to BuildArena.setTypeByPlotMembers 2022-08-11 22:34:14 +02:00
github-actions[bot] bc3085316f Bump pom.xml from 4.5.2-dev49 to 4.5.2-dev50 2022-08-11 20:22:58 +00:00
montlikadani 9361a3287e Add new theme command argument and refactor theme handling (#53)
* New theme argument and refactor

* Backport the getters for bbtheme

* New theme argument and refactor

* Removed todos and added missing GTB themes from holiday

* Close the builder inventory only once

* Correct setTheme return value

* Fix printing theme name and rename variable

* Rename join method

* Remove one time used parameter
2022-08-11 22:22:35 +02:00
github-actions[bot] e483c899ad Bump pom.xml from 4.5.2-dev48 to 4.5.2-dev49 2022-08-11 18:02:37 +00:00
montlikadani 86411bcc9c Fixed plots did not loaded correctly (#55)
Fixed AddPlotArgument
2022-08-11 20:02:05 +02:00
github-actions[bot] dd5cdaae57 Bump pom.xml from 4.5.2-dev47 to 4.5.2-dev48 2022-08-11 13:57:12 +00:00
Tigerpanzer_02 3ac2212733 Merge pull request #56 from montlikadani/fix-plots-not-appeared-in-gui
Fixed plot items not appeared in the GUI
2022-08-11 15:56:39 +02:00
montlikadani 518c9dfb1b Fixed plot items not appeared in the GUI 2022-08-11 15:54:26 +02:00
github-actions[bot] 614536db2b Bump pom.xml from 4.5.2-dev46 to 4.5.2-dev47 2022-08-10 20:13:26 +00:00
Tigerpanzer_02 08ed6311fd Merge remote-tracking branch 'origin/development' into development 2022-08-10 22:12:34 +02:00
Tigerpanzer_02 54620667ef Fixed arenatype loading on arena registry 2022-08-10 22:12:20 +02:00
github-actions[bot] 9789b28848 Bump pom.xml from 4.5.2-dev45 to 4.5.2-dev46 2022-08-10 17:27:29 +00:00
Tigerpanzer_02 a1433b0280 Merge remote-tracking branch 'origin/development' into development 2022-08-10 19:26:48 +02:00
Tigerpanzer_02 6970fda3db check for min players team size on team arena type instead of always 2022-08-10 19:26:27 +02:00
Tigerpanzer_02 8ca266ff3f Fixed scoreboard placeholders on language.yml 2022-08-10 19:22:20 +02:00
Tigerpanzer_02 9fd54946eb Fixed placeholders that can throw exception if used to early 2022-08-10 19:22:02 +02:00
github-actions[bot] 04bcb9baad Bump pom.xml from 4.5.2-dev44 to 4.5.2-dev45 2022-08-08 20:51:13 +00:00
Tigerpanzer_02 a61fc81ead Fixed ChunkManager chunkClass issues on upper 1.17 versions 2022-08-08 22:50:40 +02:00
Tigerpanzer_02 d9ba20713b Fixed themeManager is initialized to late 2022-08-08 22:50:04 +02:00
Tigerpanzer_02 8d9b92c6e4 Fixed plot loading on startup 2022-08-08 21:33:13 +02:00
github-actions[bot] c822d2af76 Bump pom.xml from 4.5.2-dev43 to 4.5.2-dev44 2022-08-05 21:17:08 +00:00
Tigerpanzer_02 e8ebf3066c Changed color codes to bb colors
Fixed wrong name of shaded minigamesbox
2022-08-05 23:16:42 +02:00
github-actions[bot] e71e5a16c1 Bump pom.xml from 4.5.2-dev42 to 4.5.2-dev43 2022-08-04 20:26:19 +00:00
Tigerpanzer_02 8df96c6443 Merge remote-tracking branch 'origin/development' into development 2022-08-04 22:25:46 +02:00
Tigerpanzer_02 29a894367c Fixed Stats messages got different key 2022-08-04 22:22:52 +02:00
Tigerpanzer_02 416b289d44 Fixed ClassCastException on non player hits 2022-08-04 22:22:24 +02:00
github-actions[bot] 86d5df7d34 Bump pom.xml from 4.5.2-dev41 to 4.5.2-dev42 2022-08-03 20:03:20 +00:00
Tigerpanzer_02 6c6abd4ec5 Merge remote-tracking branch 'origin/development' into development 2022-08-03 22:02:44 +02:00
Tigerpanzer_02 d11da3c04a Added missing statistic messages registration 2022-08-03 22:02:37 +02:00
github-actions[bot] 71623ac112 Bump pom.xml from 4.5.2-dev40 to 4.5.2-dev41 2022-08-03 19:52:55 +00:00
Tigerpanzer_02 bd8455d6d2 Fixed disable npe, updated setup items and fixed loading of setup inv 2022-08-03 21:52:22 +02:00
github-actions[bot] edb4add549 Bump pom.xml from 4.5.2-dev39 to 4.5.2-dev40 2022-08-03 15:44:41 +00:00
J.T. McQuigg 8d5d58150d Updated maven and VersionUtils teleport use (#52)
* updates

* Move TP to Version Utils
2022-08-03 17:44:03 +02:00
github-actions[bot] 5222e1e965 Bump pom.xml from 4.5.2-dev38 to 4.5.2-dev39 2022-08-01 14:50:07 +00:00
Tigerpanzer_02 9e7d894dad Merge pull request #50 from montlikadani/clean-up
Code cleanup
2022-08-01 16:49:36 +02:00
montlikadani 23eb26c5cb Clean up code 2022-08-01 11:58:32 +02:00
github-actions[bot] 09390edc18 Bump pom.xml from 4.5.2-dev37 to 4.5.2-dev38 2022-07-03 19:29:40 +00:00
Tigerpanzer_02 7ffd8d2711 Fixed startup issues 2022-07-03 21:29:02 +02:00
github-actions[bot] e02df078b8 Bump pom.xml from 4.5.2-dev36 to 4.5.2-dev37 2022-07-03 18:06:06 +00:00
Tigerpanzer_02 1e8eb3d37a Update deploy.yml 2022-07-03 20:05:41 +02:00
github-actions[bot] ba3fed6d55 Bump pom.xml from 4.5.2-dev35 to 4.5.2-dev36 2022-07-03 18:01:16 +00:00
Tigerpanzer_02 bb6540ab9a Update deploy.yml 2022-07-03 20:00:56 +02:00
github-actions[bot] a4ad4c00e0 Bump pom.xml from 4.5.2-dev34 to 4.5.2-dev35 2022-07-03 17:59:20 +00:00
github-actions[bot] 58c8d2fc05 Bump pom.xml from 4.5.2-dev33 to 4.5.2-dev34 2022-07-03 17:49:49 +00:00
Tigerpanzer_02 4853f091c0 Merge remote-tracking branch 'origin/development' into development 2022-07-03 19:49:20 +02:00
Tigerpanzer_02 955db04be4 Updated distributionManagement 2022-07-03 19:49:11 +02:00
github-actions[bot] 90cbf1fd57 Bump pom.xml from 4.5.2-dev32 to 4.5.2-dev33 2022-07-03 17:40:05 +00:00
Tigerpanzer_02 030e831c76 Update deploy.yml 2022-07-03 19:39:35 +02:00
github-actions[bot] 4affe97022 Bump pom.xml from 4.5.2-dev31 to 4.5.2-dev32 2022-07-03 14:10:21 +00:00
Tigerpanzer_02 14a145114e Integrated new core
1.18 and 1.19 chunk support (biome update)
2022-07-03 16:09:33 +02:00
github-actions[bot] 3092428cae Bump pom.xml from 4.5.2-dev30 to 4.5.2-dev31 2022-06-17 12:21:10 +00:00
Tigerpanzer_02 71db108f91 Rework GTB arena (part of core integration, not ready to run) 2022-06-17 14:20:34 +02:00
github-actions[bot] ab2a6c73bd Bump pom.xml from 4.5.2-dev29 to 4.5.2-dev30 2022-05-29 21:46:16 +00:00
Tigerpanzer_02 313d209664 Sorting, Rework Solo and Team arena (part of core integration, not ready to run) 2022-05-29 23:45:39 +02:00
github-actions[bot] 2c87f0abfb Bump pom.xml from 4.5.2-dev28 to 4.5.2-dev29 2021-12-07 20:34:39 +00:00
Tigerpanzer_02 b1ed5db4dc Updated repo links to https 2021-12-07 21:34:00 +01:00
github-actions[bot] 0caf5e7b7e Bump pom.xml from 4.5.2-dev27 to 4.5.2-dev28 2021-11-13 17:30:21 +00:00
montlikadani 0fedca7e6b Reduce the complexity of vote event 2021-11-13 18:29:52 +01:00
github-actions[bot] ce0a3b44a4 Bump pom.xml from 4.5.2-dev26 to 4.5.2-dev27 2021-11-13 17:16:56 +00:00
montlikadani f315bb1537 Improve the startup of the arena registration 2021-11-13 18:16:21 +01:00
github-actions[bot] 8846037f02 Bump pom.xml from 4.5.2-dev25 to 4.5.2-dev26 2021-11-13 17:04:04 +00:00
montlikadani 7cf30d4022 Make sure the chance string can be parsed to double 2021-11-13 18:03:27 +01:00
github-actions[bot] 2485c94152 Bump pom.xml from 4.5.2-dev24 to 4.5.2-dev25 2021-11-13 16:57:41 +00:00
montlikadani 05a869402d Changes to rewards processing
- Slightly refactored reward performing process so now you can specify which of the console command can be performed only once as by default it performs all the console commands for all players

this is a trash made solution, but I don't have a better idea
2021-11-13 17:57:01 +01:00
github-actions[bot] 46f9503e2f Bump pom.xml from 4.5.2-dev23 to 4.5.2-dev24 2021-10-31 12:02:49 +00:00
montlikadani 042a3cccc5 Fix when retrieving current builder again
hopefully this works
2021-10-31 13:02:14 +01:00
github-actions[bot] a4aa04e2e6 Bump pom.xml from 4.5.2-dev22 to 4.5.2-dev23 2021-10-31 11:54:52 +00:00
montlikadani 89499b8aad things 2021-10-31 12:54:27 +01:00
github-actions[bot] d5744bd32d Bump pom.xml from 4.5.2-dev21 to 4.5.2-dev22 2021-10-30 21:10:25 +00:00
montlikadani cb4128653b Fixed another IndexOutOfBoundsException for retrieving next player by round 2021-10-30 23:09:48 +02:00
github-actions[bot] eae005d17e Bump pom.xml from 4.5.2-dev20 to 4.5.2-dev21 2021-10-29 15:55:21 +00:00
montlikadani 2d7167924e Use the enum constant for theme difficulty instead of string 2021-10-29 17:54:53 +02:00
github-actions[bot] 98b6cb497d Bump pom.xml from 4.5.2-dev19 to 4.5.2-dev20 2021-10-29 15:36:16 +00:00
montlikadani e966ebdb93 Fixed NPE when the saved signs arena does not existed on load 2021-10-29 17:35:34 +02:00
github-actions[bot] cb6ca3f724 Bump pom.xml from 4.5.2-dev18 to 4.5.2-dev19 2021-10-28 20:31:22 +00:00
montlikadani f8b8c9eba8 Cache random instance as we not uses seeds 2021-10-28 22:30:49 +02:00
github-actions[bot] f22db8c7ec Bump pom.xml from 4.5.2-dev17 to 4.5.2-dev18 2021-10-28 20:16:53 +00:00
montlikadani d0ca53dd6f Fixed IndexOutOfBoundsException when retrieving currentBuilder at next round 2021-10-28 22:16:16 +02:00
github-actions[bot] 72022f62b5 Bump pom.xml from 4.5.2-dev16 to 4.5.2-dev17 2021-10-15 15:29:38 +00:00
montlikadani 0d3247c5df Fixed when selecting an arena does not existed from arenaSelector menu 2021-10-15 17:29:03 +02:00
github-actions[bot] db8cbc2447 Bump pom.xml from 4.5.2-dev15 to 4.5.2-dev16 2021-10-02 20:10:34 +00:00
montlikadani ca03db8219 Fix NoSuchMethodError when Entity#setAI method is not exists under 1.9 2021-10-02 22:09:53 +02:00
github-actions[bot] 9d068cb15a Bump pom.xml from 4.5.2-dev14 to 4.5.2-dev15 2021-09-25 18:59:07 +00:00
montlikadani ffa79cd283 Small changes, ResultSet must be included to try-with statement in MySqlDatabase 2021-09-25 20:58:29 +02:00
github-actions[bot] 0a66bb97db Bump pom.xml from 4.5.2-dev13 to 4.5.2-dev14 2021-09-02 17:32:57 +00:00
montlikadani 61a62d8e88 Temporarily fixed arena selector gui to do not cause conflicts with players 2021-09-02 19:32:19 +02:00
github-actions[bot] f8ede59186 Bump pom.xml from 4.5.2-dev12 to 4.5.2-dev13 2021-08-31 08:36:44 +00:00
montlikadani 60a0b21547 Fixed when none of entities spawned in worlds due to last changes 2021-08-31 10:36:05 +02:00
github-actions[bot] 438b1ae260 Bump pom.xml from 4.5.2-dev11 to 4.5.2-dev12 2021-08-29 15:49:54 +00:00
montlikadani f1a82ccf5a Added option for the third first guessers to receive more points 2021-08-29 17:49:12 +02:00
github-actions[bot] cee0a8ce30 Bump pom.xml from 4.5.2-dev10 to 4.5.2-dev11 2021-08-29 14:54:14 +00:00
montlikadani 4ae3d387b9 Some micro opimizations for game events
- Fixed NPE when player's plot was invalid after NPC click
2021-08-29 16:53:44 +02:00
github-actions[bot] ae545f9fdd Bump pom.xml from 4.5.2-dev9 to 4.5.2-dev10 2021-08-26 17:51:20 +00:00
Tigerpanzer_02 237d350de7 Adjusted CHANGELOG.md 2021-08-26 19:50:53 +02:00
github-actions[bot] 46ec63299c Bump pom.xml from 4.5.2-dev8 to 4.5.2-dev9 2021-08-26 17:32:14 +00:00
Tigerpanzer_02 ff5455e9da Added %ARENATYPE% as placeholder for messages 2021-08-26 19:31:49 +02:00
github-actions[bot] 6ccaeef26d Bump pom.xml from 4.5.2-dev7 to 4.5.2-dev8 2021-08-19 11:10:22 +00:00
montlikadani 6436d5934d Small optimizations 2021-08-19 13:09:40 +02:00
github-actions[bot] 86804e5760 Bump pom.xml from 4.5.2-dev6 to 4.5.2-dev7 2021-08-08 21:37:34 +00:00
Tigerpanzer_02 baf0570f0d Fixed mysql create table statement 2021-08-08 23:37:05 +02:00
github-actions[bot] 154b0e4f08 Bump pom.xml from 4.5.2-dev5 to 4.5.2-dev6 2021-08-06 12:27:31 +00:00
montlikadani 34d15f8074 Trash made solution to do not perform console reward commands more than once 2021-08-06 14:26:58 +02:00
github-actions[bot] ebba46eb74 Bump pom.xml from 4.5.2-dev4 to 4.5.2-dev5 2021-08-05 12:53:59 +00:00
montlikadani e3f024ea43 Small optimization for reward giving for players
- Fixed issue when player's inventories did not get cleared before teleport. This is mostly reproducible in multiple worlds where the lobby is in another and the game is in another.
2021-08-05 14:53:15 +02:00
github-actions[bot] a1b5e615e7 Bump pom.xml from 4.5.2-dev2 to 4.5.2-dev3 2021-08-04 17:20:06 +00:00
montlikadani 67ab992852 Now you can configure the notification of the remaining build time 2021-08-04 19:19:34 +02:00
github-actions[bot] e7ef2309bb Bump pom.xml from 4.5.2-dev1 to 4.5.2-dev2 2021-08-04 16:32:12 +00:00
montlikadani 541b9a04e7 Plot should only be reseted after players got rewards in GTB 2021-08-04 18:31:40 +02:00
github-actions[bot] c3bedae55b Bump pom.xml from 4.5.2-dev0 to 4.5.2-dev1 2021-08-04 15:46:11 +00:00
montlikadani c23d11d3b3 Some small changes in rewards 2021-08-04 17:45:33 +02:00
github-actions[bot] d332a0c070 Bump pom.xml from 4.5.2 to 4.5.2-dev0 2021-08-04 15:27:06 +00:00
montlikadani d537c0b8cd Fixed when players didn't got rewards after plot reset
Now the player's plots will be reseted after players got teleported to lobby and they got rewards.
2021-08-04 17:26:21 +02:00
Tigerpanzer_02 20859da95d Merge pull request #47 from Plugily-Projects/development
4.5.2
2021-08-03 20:06:54 +02:00
Tigerpanzer_02 4b8dd3a848 Merge pull request #45 from Plugily-Projects/development
4.5.1
2021-08-02 20:36:46 +02:00
Tigerpanzer_02 373e6c05d7 Merge pull request #44 from Plugily-Projects/development
4.5.0
2021-04-13 20:34:29 +02:00
Tigerpanzer_02 c5451d3594 Merge pull request #43 from Plugily-Projects/development
4.4.9
2021-03-19 21:52:07 +01:00
Tigerpanzer_02 cf1c96c3f7 Merge pull request #42 from Plugily-Projects/development
4.4.8
2021-03-17 22:24:47 +01:00
272 changed files with 23498 additions and 18837 deletions

No files matched your search

-271
View File
@@ -1,271 +0,0 @@
<?xml version="1.0"?>
<!--
~
~ BuildBattle - Ultimate building competition minigame
~ Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
~
-->
<!--
~ Murder Mystery is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation; either version 3 of the License, or
~ (at your option) any later version.
~
~ Murder Mystery is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with Murder Mystery. If not, see <http://www.gnu.org/licenses/>.
-->
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
that can be found at https://google.github.io/styleguide/javaguide.html.
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
To completely disable a check, just comment it out or delete it from the file.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="250"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="LeftCurly"/>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
</module>
<module name="MethodParamPad"/>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation"/>
</module>
</module>
+1
View File
@@ -0,0 +1 @@
.gitea/CODEOWNERS linguist-detectable=false
+3
View File
@@ -0,0 +1,3 @@
# Pull requests request review from the eligible staff team(s).
# One approval from either an Admin or Developer satisfies branch protection.
* @trueog/Admins @trueog/Developers
-1
View File
@@ -1 +0,0 @@
patreon: plugily
-11
View File
@@ -1,11 +0,0 @@
## Issue name
### Sort description of issue
## Error code
```
code in ``` tags
```
## Additional info
- Spigot version:
- Plugin version:
-31
View File
@@ -1,31 +0,0 @@
![](https://images.plugily.xyz/banner/display.php?id=BuildBattle)
# Build Battle [![](https://img.shields.io/badge/javadocs-latest-green.svg)](https://jd.plugily.xyz/apidocs/minecraft/buildbattle) [![](https://img.shields.io/badge/wiki-click-blue.svg)](https://wiki.plugily.xyz/minecraft/buildbattle/index.php) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=Plugily-Projects_BuildBattle&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=Plugily-Projects_BuildBattle) [![Discord](https://img.shields.io/discord/345628548716822530.svg?color=7289DA&label=discord)](https://discord.gg/UXzUdTP)
BuildBattle is a Minecraft minigame designed for small and big servers. This minigame is unique and very configurable, 100% free and open source!
The goal is to build the best you can! You must compete with other players in this building game. Who will be the best?
Have fun using it! Leave a good rating if you really like it.
## Want to contribute in this project?
[**💣 Issues Reporting (Discord)**](https://discordapp.com/invite/UXzUdTP)        [**❤ Make Donation**](https://www.paypal.me/plugilyprojects)
# Credits
## Open Source Libraries
| Library | Author | License |
|-------------------------------------------------------------|-------------------------------------------------|----------------------------------------------------------------------------|
| [InventoryFramework](https://github.com/stefvanschie/IF/) | [stefvanschie](https://github.com/stefvanschie) | [Unlicense](https://github.com/stefvanschie/IF/blob/master/LICENSE) |
| [ScoreboardLib](https://github.com/TigerHix/ScoreboardLib/) | [TigerHix](https://github.com/TigerHix) | [LGPLv3](https://github.com/TigerHix/ScoreboardLib/blob/master/LICENSE) |
| [HikariCP](https://github.com/brettwooldridge/HikariCP) | [brettwooldridge](https://github.com/brettwooldridge) | [Apache License 2.0](https://github.com/brettwooldridge/HikariCP/blob/dev/LICENSE) |
| [bStats](https://github.com/Bastian/bStats-Metrics) | [Bastian](https://github.com/Bastian) | [LGPLv3](https://github.com/Bastian/bStats-Metrics/blob/master/LICENSE) |
| [Commons Box](https://github.com/Plajer/Commons-Box) | [Plajer](https://github.com/Plajer) | [GPLv3](https://github.com/Plajer/Commons-Box/blob/master/LICENSE.md) |
## Open Source Licenses
#### Code Whale
<img src="https://poeditor.com/public/images/logo/logo_head_500_transparent.png" alt="jetbrains logo" width="150"/>
Thanks to Code Whale for Open Source license for POEditor project.
## Contributors
<a href="https://github.com/Plugily-Projects/BuildBattle/graphs/contributors">
<img src="https://contrib.rocks/image?repo=Plugily-Projects/BuildBattle" />
</a>
<img align="right" src="https://i.imgur.com/EmFfDXN.png">
-65
View File
@@ -1,65 +0,0 @@
# This is a basic workflow to help you get started with Actions
name: deploy
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ development ]
# pull_request:
# branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
deploy:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Bump Version
id: bump
uses: Plugily-Projects/maven-version-bump-action@dev
with:
github-token: ${{ secrets.github_token }}
- uses: actions/cache@v2
with:
path: ~/.m2/repository
key: maven-${{ hashFiles('**/pom.xml') }}
restore-keys: maven-
- name: Set up Maven
uses: stCarolas/setup-maven@v4
with:
maven-version: 3.6.3
- name: Set up JDK 16
uses: actions/setup-java@v1
with:
java-version: 16
- name: maven-settings-action
uses: s4u/maven-settings-action@v2.4.0
with:
servers: |
[{
"id": "${{ secrets.PLUGILY_MAVEN }}",
"username": "${{ secrets.PLUGILY_MAVEN_USERNAME }}",
"password": "${{ secrets.PLUGILY_MAVEN_PASSWORD }}"
},
{
"id": "${{ secrets.PLUGILY_JD }}",
"username": "${{ secrets.PLUGILY_JD_USERNAME }}",
"password": "${{ secrets.PLUGILY_JD_PASSWORD }}"
}]
- run: mvn clean verify compile package site:site site:deploy deploy -f pom.xml
-48
View File
@@ -1,48 +0,0 @@
name: sonarcloud
on:
push:
branches:
- development
- dev
- main
- master
pull_request:
types: [opened, synchronize, reopened]
jobs:
sonarcloud:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 16
uses: actions/setup-java@v1
with:
java-version: 16
- name: Set up Maven
uses: stCarolas/setup-maven@v4
with:
maven-version: 3.6.3
- name: Cache SonarCloud packages
uses: actions/cache@v1
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache@v1
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
+52 -6
View File
@@ -1,7 +1,53 @@
/.idea/
/out/
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
# ...but the vendored dependency jars and the Gradle wrapper are tracked on purpose. Without these
# negations, bumping a vendored jar to a new filename would be silently skipped by `git add`.
!libs/*/*.jar
!gradle/wrapper/gradle-wrapper.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
# macOS system files
.DS_Store
# gradle build output files
build/
.gradle/
# eclipse project files
.settings/
.project
.classpath
.checkstyle
bin/
# IntelliJ files
.idea/
.kotlin
*.iml
/target/
/minecraft/
/docs/
.*
*.ipr
*.iws
out/
# Claude Code local settings
.claude/
+9
View File
@@ -0,0 +1,9 @@
[submodule "libs/Utilities-OG"]
path = libs/Utilities-OG
url = https://git.trueog.net/trueog/Utilities-OG
[submodule "libs/MyWorlds"]
path = libs/MyWorlds
url = https://git.trueog.net/trueog/MyWorlds
[submodule "libs/Scoreboard-OG"]
path = libs/Scoreboard-OG
url = https://git.trueog.net/trueog/Scoreboard-OG
+254 -471
View File
@@ -1,504 +1,287 @@
## Build Battle Changelog
# Changelog
Changelog is followed by special scheme which is required in order to allow automatic discord
deploy webhooks to print changelog successfully
All notable OG-fork changes are documented here. Upstream history is at
https://github.com/Plugily-Projects/BuildBattle.
## Log scheme
`### <current version from pom.xml> <anything else here>`
`<update log line>`
## 5.1.12 - 2026-09-16
That's all, matcher will stop when detects next line started with `###` match
### 4.5.2 Release (02.08.2021 - 03.08.2021)
* Fixed issues with spectators get added multiple times to the players list
* Fixed Cannot invoke because "userPlot" is null
### Changes
### 4.5.1 Release (15.04.2021 - 02.08.2021)
* Added 1.17 support
* Added adjustable team mode plot size
* Added placeholder total_points_earned and highest_points
* Added plot selector for team mode
* Added greek as language (Thanks to poeditor contributors)
* Renamed class paths from commonsbox
* Reuse XMaterial for specialitems
* Fixed teamarena does not stop when only two players are left from the same team
* Fixed spectatormode does not display summary and players
>>> b1
* Added forcestart item
* Added new message In-Game.Floor-Item-Blacklisted
* Added /bb guess <word> argument (useful for servers with bungee handled chat)
* Added placeholder arena_players_online
* Added /bb join maxplayers type which tries to get the arena with the highest amount of players
* Added special_items.yml
* Added changeable options menu item
* Changed randomjoin mechanics -> Searches for starting -> random join -> Searches for waiting -> random join
* Changed Now builders will also get points if the building is guessed
* Changed gtb word hints are now randomly chosen
* Changed gtb word hints will stop if there are only 2 chars left to show
* Changed empty message is no longer sent
* Fixed gtb guessers got options menu on there inventory
* Fixed on gtb the time and weather is not synced with all players
* Fixed minecarts can go outside of plot
* Fixed item frames can be rotated outside plot
* Fixed some bugs on particle menu
* Fixed when plugins scoreboards not re-appeared after game end
* Fixed players can report more than one time
* Fixed spectator mode does not work correctly
* Fixed gtb guesser players can teleport to all players on the server
* Removed lobbyitems.yml
* Removed temp added scoreboard rewards
- Classic and Teams matches are played in rounds. `Time-Manager.<Classic|Teams>.Rounds`
(default 3) sets how many builds a match holds; each round announces its own
theme, runs `In-Game` seconds of building, then walks every plot for a vote.
Plots are wiped between rounds, the votes add up, and the highest total after
the last round wins. `Rounds: 1` is the old single-build flow.
- `Time-Manager.<Classic|Teams>.Random-Theme` (default on) lets the plugin draw
each round's theme at random from `themes.yml` instead of holding the vote, so
building starts at once. Off, the vote runs before every round. Either way a
theme is never repeated within a match while unused ones remain.
- Shipped `In-Game` shortened to 150 seconds for Classic and 180 for Teams to
fit three rounds. The config migration only adds the two new keys to an
existing `config.yml`; lower `In-Game` there by hand.
- The Classic theme list in `themes.yml` grows from 60 to 146 entries, leaning
on concrete objects, animals, vehicles and food that fit a short round.
- Round announcements are the new `In-Game.Messages.Plot.Round.Start` and
`.Title` keys in `language.yml`, added to an existing file by the language
migration; `%arena_round%` and `%arena_rounds%` placeholders resolve in
Classic, Teams and Guess The Build. The sidebar shows `Round: 1/3` and the
boss bar phase reads `Building 1/3` whenever a match has more than one round.
- Plot vote shortened from 20 to 15 seconds per plot in the shipped `config.yml`
(`Time-Manager.<Classic|Teams>.Voting.Plot`); the migration leaves an
existing value alone.
- Builders are no longer teleported to the plot spawn for straying five blocks
past the plot. Each player now has `Plot.Border.Grace` (default 3) blocks of
room outside their plot, and the one-block shell beyond that is drawn for
them alone as a rainbow stained-glass wall (`Plot.Border.Block`, also
`RAINBOW_WOOL`, `RAINBOW_TERRACOTTA`, `RAINBOW_CONCRETE` or any block) through
client-side block changes, within `Plot.Border.Distance` (default 8) blocks of
them. Nothing in the world changes and other players never see it. The wall
covers all six faces, skips real solid blocks and is only drawn during build
time; in Guess The Build it surrounds the plot being built. A move that would
still end past the wall is cancelled, and anyone found beyond it by any other
route (teleport, vehicle, the three-second sweep) is pulled to the nearest
legal spot at their own height, or to the plot spawn if that spot is blocked.
`Plot.Border.Enabled: false` hides the wall and keeps the limit;
`Plot.Move-Outside: true` still lifts it altogether. Derived from
EternalCombat's border module (Apache License 2.0) via Duels-OG, with the
notice kept in `PlotBorderManager`; the config migration adds the
`Plot.Border` block.
- `LanguageMigrator` no longer falls through from the language.yml update into
the heads main-menu update.
### 4.5.0 Release (21.03.2021 - 13.04.2021)
* Automatically disable bossbar support on 1.8 to prevent issue if bossbar is enabled on config.yml
* Fix when arena selector GUI does not opened
* Fixed HolidayManager that crashes themes on Teams and GTB mode
* Fixed NPE on ArrowEvents and other version improvements
## 5.1.11 - 2026-09-14
### 4.4.9 Release (19.03.2021)
* Added configurable arena selector items (per state)
* Fixed particle issues on some versions
### Changes
### 4.4.8 Release (08.02.2021 - 17.03.2021)
* Added option to perform command after specific amount of reports
* Added list of restricted entities that can't be spawned in game
* Added legacy support
* Added super_votes papi placeholder
* Added TeleportArgument (/bba tp)
* Added new RewardType scoreboard_remove
* Added modifiable arena state names to language
* Fix when sign instances section is null in some cases
* Fix when some inventory can't be opened in game
* Moved statistic save method inside onDisable
* Changed prevent interaction with enderchest
- The arena sidebar now follows the Scoreboard-OG network board's look: a
`♥ BuildBattle-OG ♥` title, one blank line between labelled blocks and a
`true-og.net` footer. The lobby card shows the mode, map, player count and
countdown; Classic and Teams show the theme, phase, clock, player count or
teammate and the plot being judged; Guess The Build shows the builder, the
theme the viewer may know, round, clock, own points and the leader; the end
card names the winner. Lines are built in code, so the `Scoreboard.Content`
lists in `language.yml` are no longer read, and every line stays within 16
legacy characters so 1.8 clients on ViaBackwards see it uncut.
- Arena worlds no longer come up as vanilla terrain. The shaded MiniGamesBox
deserializes arena locations with `Bukkit.createWorld(new WorldCreator(name))`
for any world that is not loaded, so the first boot after 5.1.10 shipped the
ready-made `BB1` arena generated plain overworlds named `BB1-map` and
`BB1-hub` when the map folders were not in place yet, and MyWorlds recorded
them with an empty chunk generator. `ArenaRegistry` now refuses to register
an arena whose worlds cannot be loaded from an existing folder, so that path
is never reached.
- Maps are stored under a cold-storage directory instead of the server root,
the way Splegg-OG and TheHerobrine-OG do it: `MyWorlds.Map-Base` (default
`maps`, relative to the server root) holds one folder per map. On every
enable each world named in `arenas.yml` is resolved to `<Map-Base>/<Name>/`
(case-insensitively, ignoring `-` and `_`, and for an arena's game world also
by its `mapname`, so `BB1-map` finds `maps/Plaza` and `BB1-hub` finds
`maps/BB1_Hub`), any loaded copy is unloaded, the server-root copy is deleted
and replaced with a fresh copy, and MyWorlds loads it. A world without a map
there is loaded from the server root as before. Set `Map-Base` empty to turn
the copy off.
- Bundled `BuildBattle-OG:void` chunk generator, pinned onto every arena world
the plugin loads unless MyWorlds already has one for it
(`MyWorlds.Void-Generator`), so chunks outside the saved map stay void.
- README: Quick Setup no longer asks for a manual copy to the server root or
`/mw load`; the Bundled maps and Configuration sections describe the map
directory and the two new keys.
- The boss bar is now a timer for the current phase instead of MiniGamesBox's
rotating messages. Its title names the phase (waiting with the player count,
starting, theme vote, building, plot vote, builder picking a theme, guess the
build, next round, game over, restarting) with a `mm:ss` clock and
`true-og.net`, its colour follows the phase and it drains from full to empty
as the phase runs out. `BaseArena` records the length of each phase from the
timer and state changes, `PhaseBossbarManager` is returned from
`getBossbarManager()` so MiniGamesBox's own join and leave hooks drive it,
and `Bossbar.Interval` in `config.yml` no longer has an effect.
- Every `plugily.xyz` link a player could see in game now reads `true-og.net`:
the boss bar, the `Bossbar` and `Scoreboard` lists in `language.yml` and
`locales/language_default.yml`.
### 4.4.7 Release (24.01.2021 - 28.01.2021)
* Fixed Join SubTitle not being sent
* Fixed stack trace array length is 0 when trying to send exception to service
* Fix NPE related to citizens NPCRegistry method return value
* Fixed spectators can not see each other after joining game while being ingame
* Added 2 new Plot times - Noon, MidNight
## 5.1.10 - 2026-09-14
### 4.4.6 Release (18.01.2021 - 22.01.2021)
* Fixed bb items are not removed if inventory manager is enabled and the server is stopping
* Fixed particle refresh scheduler not worked on game start
### Changes
### 4.4.5 Release (31.12.2020 - 18.01.2021)
* ArgumentsRegistry now accessible from outside
* Fixed some reported NPEs about setup inventory
* Added start game reward action
* Added join title and subtitle
* Added customizable item name in arena selector gui (by ajgeiss0702)
* Fixed asynchronous issue when performing commands from async chat
* Optimized plot particle refresh scheduler, now it only runs when a game is running
* Only add points to plot that do not have points already
- Ship `arenas.yml` configured for the open source TrueOG maps. Arena `BB1`
now points at `Plaza` (public domain, twelve 31x31 plots around a central
plaza) as `BB1-map` and `BB1_Hub` (Green Leave Lobby, CC BY-SA 3.0) as
`BB1-hub`, with all twelve plot cuboids, the plaza centre as start and
spectator location, the hub spawn as lobby and end location, and
`maximumplayers: 12`. A fresh install needs the two worlds copied in and
registered with MyWorlds, nothing else. Both maps live under `maps/` in the
true-og repository.
- README: Quick Setup follows the bundled-map path first; the manual setup GUI
flow is kept for custom arenas and additional lobbies. New "Bundled maps"
section documents the worlds, licenses and layout.
### 4.4.4 Release (18.12.2020 - 29.12.2020)
* Rewritten scoreboardlib (fixed flickering and color matching) -> 122 chars for 1.14 up and 48 for lower versions
* Fix async catch exception in old versions when teleporting players to their plots
* Fixed setup menu on "normal" spigot servers
## 5.1.9 - 2026-09-12
### 4.4.3 Release (30.11.2020 - 13.12.2020)
* Fixed joining through a sign while hotbar slot for leave-item is active
* Fixed cast exception when banner meta is not item
* Fixed NoSuchMethodError when CommandSender#spigot does not exists on 1.11
* Fixed BiomeChange specially on 1.15 (PacketPlayOutMapChunk)
* Fixed Command-Instead-Of-Head-Menu is not executed on the first menu
* Fixed lore is not updating on setup inventory
* Fixed ANNOUNCE_PLOTOWNER_LATER did not show both owners on team mode
### Changes
### 4.4.2 Release (02.10.2020 - 12.11.2020)
* Fixed spectators are able to damage entities
* Fixed NPE related to arenas config not loaded correctly
* Fixed for 1.11 player heads
* Fixed particles can't activate again after they got removed
* Fixed spectators can't fly after changing world
* Signs performance improvement
* Fixed (some related) script NPE on rewards.yml
* Now you can disable spectators from joining into game
* Now walk and fly speed will reset on join and leave
* Fixed particle remover does not auto update
* Fixed particle remover locations are multiply times listed
* Fixed debug messages to console are not colored
* Fixed NPE related to vote menu updating
- Claim `/hub`, `/lobby` and `/spawn` inside BuildBattle worlds before any other
plugin sees them, the way `/vote` already is. Splegg-OG and TheHerobrine-OG
register `/hub` as well, and Bukkit hands the bare label to whichever plugin
loads first, so an arena player's `/hub` could run another minigame's command
and teleport them out while the arena still counted them; Spawn-OG's `/spawn`
did the same. `/lobby` is now an alias of `/hub` everywhere, and the three
labels are topped up into `Commands.Whitelist` on startup so MiniGamesBox's
in-game command block does not report them.
- `/bb join` and `/bbjoin` with no lobby list every arena with its state, fill
and a clickable join line, like `/hbjoin`. `/bb join` now also accepts a bare
number (`/bb join 1`) and a case-insensitive id, and replaces the bundled
MiniGamesBox join argument.
### 4.4.1 Release (15.08.2020 - 20.09.2020)
* (Developer Alert - Class rename)
* Added spectator mode
* Added GTB to the SetUp inventory
* Added arena selector
* Added support for 1.16 hex colors
* Fixed NPE when teleporting players to plots
* Fixed IllegalArgumentException when some particles have "custom class data"
* Fixed voting plot owners is empty
* Fixed NoSuchMethodException for player chunk map
* Fixed NPE during giving rewards to players
* Fixed LanguageMigrator breaking language.yml
* Fixed NoClassDefFoundError on pre 1.16 servers
* Fixed NPE during vote event
* Fixed votes command
* Fixed for new 1.16 wall signs
* Fixed NPE regarding giving rewards to players and resetting the plot areas
* Fixed when blacklisted items & floor material is not exists and throws errors
* Fixed async catch from bukkit when performing commands
* Fixed IllegalPluginAccessException on plugin disable
* Fixed NPE on Plotreset (GTB)
* Fixed player being kicked when trying to join an in-game arena
* Fixed NPE when trying to teleport players to lobby location
* Fixed PlaceholderAPI placeholders not works on scoreboard in guessTheBuild mode
* Fixed problems with materials
* Reworked version checker
* Improved the tab complete handling
* Updated PlaceholderAPI dependency
* Updated locales to latest version
* Added the possibility to change messages of locales on language.yml
## 5.1.8 - 2026-09-12
### 4.4.0 Release (01.07.2020 - 29.07.2020)
* GuessTheBuild release
* Reworked whole Rewards
* New file rewards.yml
* Added short commands such as start and leave
* Added option to disable separate chat
* Added possibility to change table name of mysql database
* Added possibility to run command for report item
* Added the new particles from 1.13 and up
* Added an option to disable party features
* Added missing 1.14 & 1.15 & 1.16 Materials/Biomes
* Added 1.16.x compatibility
* Added adjustable floor blacklist
* Added bungeemode Arena shuffler
* Added players will get kicked on bungeemode when arena is full and has no rights
* Added an event to cancel fire spread on the plot
* Added option to announce plot owner after voting
* Fixed force start command when setting forced theme didn't set build time properly
* Fixed bungeemanager enable null text error
* Fixed biomes on 1.16 (nosuchmethoderror)
* Fixed last plot on teammode can get double points
* Fixed rewards are ignoring the place
* Fixed HandlerList Error
* Fixed water and lava as floor material
* Fixed team member leave plot reset
* Fixed water/lava flow and piston outside of plot in worst cases
* Fixed nether star (options menu) duplication
* Tried to fix Server crash on 1.15
* Migrator for new config file as there are some more changes
* Update setup tips Feedback page link
* Randomjoin command will now longer send proper message when no arena is available
* Changed mysql updates to do only one instead of more than 10 (should improve performance)
* Updated particles.yml (Thanks Fabian Adrian #6234)
* Changed increased npc finder to radius of 5 to the plot
* Optimized floor change to get all materials
### Changes
### 4.3.2 Release
* Added per particle disabler
* Fixed Already-Playing message on randomjoin command
* Fixed Type-Arena-Name language
- Render the arena sidebar through Scoreboard-OG's sidebar API when Scoreboard-OG
`1.2.0` or newer is installed, so the network board comes back by itself after a
match and `/togglescoreboard` is honoured. Without it the MiniGamesBox board is
used as before.
- `/hub` now puts MiniGamesBox's inventory snapshot back before the teleport home.
The snapshot is taken after the teleport into the arena, so it belongs to the
arena world's MyWorlds inventory; restoring it after the teleport overwrote the
survival inventory MyWorlds had just swapped back in.
- MyWorlds settings are applied at runtime only, the way TheHerobrine-OG and
Splegg-OG do it. `MyWorlds/config.yml` is no longer rewritten on startup.
- The locale service stub no longer carries the remote fetch code; every fetch
answers with an empty stream, so the bundled locale is the only one that loads.
- Plot teleport targets are resolved on the main thread instead of a ForkJoin
worker reading block state.
### 4.3.1 Release (31.03.2020)
* Fixed Heads in lower version than 1.15.X
* Fixed bungee value Shutdown-When-Game-Ends
* Fixed automatic bungee arena restart (Now scoreboard and Bossbar applies)
* Tried to fix parties compatibility
* Fixed broken language migrator
## 5.1.7 - 2026-08-24
### 4.3.0 Release (17.03.2020)
* PlaceholderAPI placeholders are no longer case sensitive
* Added arena state placeholders for PlaceholderAPI:
* %buildbattle_{arena id}:{data}% where data types are:
* players - amount of players in arena
* max_players - max players in arena
* state - current state raw enum name eg. STARTING
* state_pretty - prettified name of enum eg. Waiting (instead WAITING_FOR_PLAYERS)
* mapname - name of arena map
* arenatype - raw enum name of arena (SOLO, TEAM etc)
* arenatype_pretty - prettified name of enum eg. Classic (instead SOLO)
* Fixed VoteMenu NullPointerException
* Added Parties support for PAF and Parties
* Now if user don´t vote the plot will get 3 points of this player to prevent unfair game behaviors
* FIXED 1.15.X Head issues
* Added Connect-To-Hub boolean to bungee.yml
* Added End-Location-Hub boolean to bungee.yml
* Fixed mysql database - Create a new one and your stats should be saved correctly
### Changes
- Register `<bb_score>` and `<bb_rank>` MiniPlaceholders through Utilities-OG.
`<bb_score>` is the player's `POINTS_TOTAL`; `<bb_rank>` maps it onto a
builder-themed ladder (Apprentice through Master Builder, then Inception's
Forger, Dreamer, Extractor and Dom), with Dreamweaver reserved for
the top scorer once they also hold Dom.
### 4.2.0 Release (16.11.2019 - 13.12.2019) (by Tigerpanzer)
* Fixed arena deletion
* Added a item to go to main options page
* Fixed Holiday themes
* Added a new MOTD Manager in the bungee.yml (Now you can define the message on your self)
* Now the values in bungee.yml will work
* Now the biomes permissions will work
* Added new check for setup validation (now registered plots amount will be checked)
* Added 1.15 compatibility
- Back both with a plugin-wide score cache seeded from the stats backend on
enable and kept live by MiniGamesBox's statistic change event, so values are
current the moment a game's points are awarded.
### 4.1.0 Release (13.07.2019 - 18.10.2019) (by Tigerpanzer and Plajer)
* Added new permission to join full games "buildbattle.fullgames"
* Added the option to join when a game is full (you will kick a player without perm)
* Fixed issue that you could join full games before they started now proper full game
permission check will occur and do the thing to allow or disallow you to join
* Fixed file creating for bungee.yml
* /bb randomjoin will now really join random arena not first one it find good to join
* Added a new option to block commands ingame
* Fixed the NoSuchMethodException on arena sign load when the sign isn´t a wallsign
* Added Chinese (Traditional) locale (zh_tw prefix)
* Changed Chinese (Simplified) locale prefix from zh to cn
* Added 1.14 support
* Added sounds when using vote items (reset voteItems.yml to see changes)
* Added banner builder in GUI
* Entities can't be damaged anymore in voting stage
* Players hiding feature is now fully removed, it was buggy
## 5.1.6 - 2026-08-17
### 4.0.2 Release (15.06.2019 - 13.07.2019)
* Join permission message outputs required permission node now
* Biome menu won't throw errors when using it now
* Fixed firework spawn after the game if they were disabled in config
* Fixed odd game behaviour when game couldn't start because there were some lacking plots
when player left game before he was removed from the plot
* Locales with special characters like Russian or Korean will now work properly and won't be seen as `?` characters
* Fixed locales might not work in fresh install of plugin
* Added 6 new locales: Portuguese (BR), Slovenian, Dutch, Lithuanian, Japanese and Italian (thanks a lot to our POEditor contributors!)
* Fixed Russian locale didn't work
### Changes
### 4.0.1 Release (11.06.2019)
* Fixed game wouldn't start if there were 2 players or more, sorry
* Fixed error occurred when you didn't look at sign while adding sign via setup GUI
- Join signs now match TheHerobrine-OG's style: gold map name, black-on-sign
player counts, and bold `JOIN` / `STARTING` / `LIVE` / `FULL` / `ENDING` /
`RESTARTING` state labels. A language-file migration (version 3) rewrites the
sign lines and `Placeholders.Game-States` on existing installs while leaving
the MOTD state labels unchanged.
### 4.0.0 Release (10.06.2019)
* Fixed typo in message accessor for guess the build game mode message
* Now players aren't saved async in onDisable method which led to exceptions in disable stage
* Fixed bad logic of assigning players to teams in teams game mode
* Teams game mode require now to have at least 3 minimum players to play, it will set it to 3 if
it's set lower
* Improved faster and more efficient scoreboard library (thanks to TigerHix)
* Reload and arena delete commands now require confirmation to execute, you must type the command twice to confirm the action
* Implemented faster Hikari database connection pool library instead of BoneCP, jar is now 3 times smaller
* First time database creation is now made async not in main server thread
* Apache Commons-io library is shaded into the jar now, 1.14 removed it
* You cannot set non occluding blocks as a floor block
* **CRITICAL** Players received packets that would break their chunks nearby them due to wrong arena plot reset check, now it's fixed
* Debug in config is no longer visible by default, no one need it
* Removed hiding/showing players in-game and outside game thing, it was bugged and better to avoid problems with it
* Fixed game ending message was never showed when using any of the locales (accessor was broken)
* /bba reload command was undeprecated and it's usage is no longer discouraged
* Made /bb help and /bba help commands actually working
* Added not playing message node to language.yml, locales already had it somehow
- Arena chat now renders the standard TrueOG name segment (union bracket tag,
display name, LuckPerms suffix) like TheHerobrine-OG, with a caret colored by
the sender's Chat-OG message color, while keeping the queue count, `SPEC`,
`VOTE` / `JUDGING`, and theme prefixes.
### 4.0.0 Beta Pre Releases 3-15 (03.10.2018 - 06.06.2019)
> RC 2
* Fixed plugin couldn't start if Cloudflare was blocked in your country (or services were offline)
* Removed locale suggester, it will no longer spam console when English (default) locale is used
* Fixed issue with plot adding via setup menu
> RC 1
* Fixed animals couldn't spawn and breed outside arenas
* Fixed spawning animals on arena even if option for disable-spawning was false
* Fixed /bba addnpc didn't work
* Fixed setup GUI didn't work properly
* Fixed [#612 exception when registering arenas](https://www.plajer.xyz/errorservice/viewer.php?id=612) when arenas.yml file was empty
* Fixed [#610 exception when special item didn't have material-name section set](https://www.plajer.xyz/errorservice/viewer.php?id=610) now by default
it will have BEDROCK value if absent
* Added pro tips about user voice and /bba votes executable from console too
> Pre 15
* Fixed [#595 /bb randomjoin command exception](https://www.plajer.xyz/errorservice/viewer.php?id=595) when no arena type
args were specified
* Fixed [#592 /bba addplot command exception](https://www.plajer.xyz/errorservice/viewer.php?id=592) when no arena name
was typed
* Fixed [#589 options menu click exceptions](https://plajer.xyz/errorservice/viewer.php?id=589) when click was on
air or outside inventoryView slots
* Fixed Signs weren't updating if Signs-Block-States-Enabled option was false
* Abandoned the direct try-catch exception handling in most of methods and event listeners in favour of
logger listening, code looks better now
* Implemented Holiday Events for April Fools, Christmas and Halloween, special themes
for solo and teams will be applied if enabled
> Pre 14
* Fixed time couldn't be set for plots because we were checking raw slot click instead of normal slot
* Made particles.yml particle items more user friendly (lores and names looks now better)
* Fixed bba addplot command didn't work properly
* Added fully configurable biomes in biomes.yml
* Fixed biomes are now properly reset in plot reset option and after arena reset
* Added "Go Back" button in particles remove menu
> Pre 13
* Added GuessTheBuild game mode (alpha)
* When using super vote you won't see two game prefixes now
* Merged /bba addvotes and /bba setvotes into /bba votes add/set command
* Added message sent to player when receives super votes
> Pre 12
* Added BBPlayersPlotReceiveEvent to API
* Fixed /bba forcestart wasn't working properly
* Added BBPlotResetEvent to API
* Particles speed is now 1, they may behave better for builders now
* Now you can properly execute all /bb and /bba commands in-game while being non op player
* Somehow plugin was lacking lobby events and you could lose food and health in lobby
* Added chat events so in-game chat is no separated from server chat (I thought it's obvious)
* Now after selection of head in heads inventoryView won't be closed, user will close it when he wants
* Now language manager will use cached language.yml file so plugin will perform bit better
* Theme vote GUI is now properly listening for click events, you don't need to click few times to make it vote
* Added useSSL=false argument in mysql.yml address to avoid mysql warnings in console (not harmful)
* Whole plugin runs now definitely faster and code execution time and plugin load decreases in timings
* Setup GUI option for setting min/max players amount now runs smoothly
> Pre 11
* Added biomes in Options menu
* Added time in Options menu
* Code improvements and changes
* Fixed arena signs were incorrectly saved via setup menu (4.0.0 pre issue)
> Pre 10
* Added setup tutorial link to setup menu
* Added tip about downloadable maps when no arenas are set up while typing /bba list
* Fixed exp not saving properly with InventoryManager
> Pre 9
* Fixed NPE when player was null (https://plajer.xyz/errorservice/viewer.php?id=347)
* Code must be changed to avoid those NPE's in the future
> Pre 8
* Fixed NPE because of wrong string access in code
* Locales will be now automatically disabled in this version - ppl don't read warnings about locales so I force them
to disable
* Now /bba reload /bba addvotes/setvotes and /bba list can be now properly executed from console
> Pre 7
* Updates are now checked async without freezing the main thread which caused TPS to drop a bit
> Pre 6
* Particles in menu are now incrementing automatically
* Particle redstone requires DustOptions and causes errors so it was removed from menu
* Fixed possible NPEs in block spread event (https://plajer.xyz/errorservice/viewer.php?id=282)
* Fixed NPE when teleporting to plot, now players will be teleported 1 x and z block away from center if
height reach Y plot limit (https://plajer.xyz/errorservice/viewer.php?id=283)
> Pre 5
* You cannot join game now infinitely through command (lol????)
* Now players that will leave game will be visible by other players outside game
> Pre 4
* API change - now you can access BuildBattle API via pl.plajer.buildbattle.api
* Maybe a fix for https://plajer.xyz/errorservice/viewer.php?id=244
> Pre 3
* Removed annoying "Please enable bStats" message
* Code improvements
* Added PR0 TIPS when editing arena
## 5.1.5 - 2026-08-05
### 4.0.0 Release (20.08.2018 - 28.09.2018)
* Fixed NullPointerException for users who where no longer online
* Now using default values when they not exist in config to avoid NullPointerException from ConfigPreferences
* Fixed IllegalArgumentException when you add invalid item name to the in-game items blacklist - now it will notify you in console
* Fixed %player% placeholder wasn't parsed in /bb stats <player>
* Added PlaceholderAPI placeholders in scoreboard
* Added Russian, Czech, Romanian and Estonian locales (thanks to POEditor contributors!)
* Added dynamic locale manager system - you can now get latest locales on demand from our repository
* Fixed scoreboard color bugs (see https://i.imgur.com/kaZy5s2.png)
* Fixed update checker bugs while using my other minigames
* /bba help command is now executable via players only
* Temporarily merged PLCore to prevent issues with other plugins
* Added blacklisted themes
* Dropped 1.9-1.10 support
* Fixed bug where plot floor wasn't reset while using Citizens
* Fixed message You became 1th/2th/3th was displayed - it shouldn't and it wasn't grammatically okay
* Added extra permission "buildbattle.command.bypass"
* Added solo and team themes
* Added cancel lobbystart when there are not enough players
* Fixed bedrock was displayed in plot floor change option menu
* Head blocks textures are now loading instantly and do not cause server to freeze at the start now
* Fixed /bb top was reversed while MySQL was enabled
* Disabled game end rewards by default because they were confusing for users
* Fixed server was stopped using Shutdown-When-Game-Ends option but player just left not started arena
* Player will be given now survival gamemode on server stop
* Removed unused code for entities
### Changes
### 3.5.1 Release (17.08.2018)
* Fixed NumberFormatException for language.yml migrator - this error is very rare to occur in normal environment but it was reported so I fixed it
* Fixed NullPointerException for plot adding via selector wand due to lack of code stop when message with not full selection was sent
* Fixed Can't fly outside plot message but you were in plot
* Fixed scoreboard contents were always in Waiting state
* Fixed IndexOutOfBoundsException in join event while bungee is enabled
* Fixed NullPointerException in scoreboard formatting while player was null
* Fixed NoDefClassFoundException in 1.13 while using sign game states
- Scope creative mode to arena builders. `BuilderCreativeManager` grants a runtime
creative exemption only while a player is an active builder inside an arena world,
and suppresses GameModeInventories-OG's inventory swap for arena participants so
the swap cannot clobber armour and offhand contents.
- Remember where a player was before they joined an arena. `PreJoinLocationStore`
keeps that location on disk, reloading an unloaded world through MyWorlds when it
is needed, and expires entries after `MyWorlds.PreJoin-Location-Expiry-Days`.
- Add the `MyWorlds.Protected-Worlds` list so arenas, plots and lobby locations can
never be placed in the server's main overworld, nether or end.
- Bundle `powerups.yml` and write it out on first start, so the shaded
MiniGamesBox-Classic reader stops logging "File powerups.yml does not exist!".
- Suppress the shaded library's "Loaded locale" console spam.
- Drop a dead clause from the console-noise filter. It tried to hide the
"you are using some fork that was not tested by us" warning, but that message is
written straight to the console sender rather than through the plugin logger the
filter is attached to, so the condition could never fire. That warning is
therefore still printed on startup; suppressing it needs a different mechanism
and is left for a later release. The "Loaded locale" suppression is unaffected
and still works.
- **Breaking:** the bundled `arenas.yml` template now names its worlds `BB1-hub` and
`BB1-map` instead of `bb_lobby` and `bb_game_1`. Chat-OG resolves a world to a
multi-world game by a `<letters><digits>-` prefix and keys the per-game Discord
channel off it, so arena worlds have to follow that shape to get scoped chat and
the Discord relay. Existing arenas keep the names they already have — changing
the template does not migrate them. To adopt the convention, rename the world
folders and update both `arenas.yml` and your MyWorlds configuration, then add a
matching `BB` entry under `discord.games` in Chat-OG's config.
- Render `language.yml` values through Utilities-OG's colorizer when that plugin is
installed, so MiniMessage tags, `<#rrggbb>` hex, `<gradient:...>`, named colours
and the `&*` rainbow code all work in messages, titles, action bars, scoreboards
and signs. Only values that actually contain such a construct are converted;
values using plain `&` codes are passed through byte-for-byte, so nothing that
ships with the plugin changes appearance. Without Utilities-OG, every value keeps
its previous formatting.
- Remove seven permission nodes from `plugin.yml` that nothing ever checked:
`buildbattle.admin.stopgame`, `.addsign`, `.plotwand`, `.create`,
`.forcestart.theme`, `.supervotes.manage` and `buildbattle.command.bypass`. The
nodes that actually gate those behaviours are `buildbattle.admin.stop`,
`.admin.locwand`, `.admin.setup` and `.command.override`; grant those instead.
In particular, bypassing in-game command blocking has always required
`buildbattle.command.override`, which was never declared, while the declared
`buildbattle.command.bypass` did nothing.
- Declare the permission nodes that were checked but never listed, including
`buildbattle.admin.setup`, `.stop`, `.locwand`, `.teleport`, `.spychat`,
`.statistic`, `.forceplay`, `.theme` and `buildbattle.command.selectplot`, so
`buildbattle.admin.*` grants the whole admin surface.
- Disable the plugin instead of half-starting it when MyWorlds is missing. The
startup check returned early after the base plugin had already enabled, leaving
the server with a plugin marked enabled but no arenas, commands or listeners.
- Suppress Guess The Build answers through Paper's `AsyncChatEvent` rather than the
legacy `AsyncPlayerChatEvent`. Registering a legacy chat listener forced the whole
server onto Paper's legacy chat path, and the handler raced Chat-OG for ownership
of the event, so a correct guess could reach the world and Discord before it was
suppressed.
- Stop `/hub` registration from throwing when the command is absent from
`plugin.yml`.
- Fix a malformed `Core-Version: 1148-` marker in `powerups.yml` that parsed as `0`
and would have left a duplicate `Do-Not-Edit` block behind on migration.
- Report `1.19` as a supported version in `internal/data.yml`, and bring
`locales/locale_data.yml` up to the current release.
- Build Utilities-OG from a git submodule, add `bootstrap.sh`, and harvest vendored
library licenses into `META-INF/licenses` automatically instead of listing them
one by one.
### 3.5.0 Release (08/16.08.2018)
* Built against PLCore API
* Hooked code with Error reporter service
* Fixed MySQL error
* Removed WorldEdit from arena usages
* Added ability to edit floor in game (requires arenas.yml edit or new setup!)
* Added joints when users have same points in voting time
* Fixed small problem when game was started and voting for theme started, timer was set for build time instead of voting time and it
could be seen in scoreboard for a second
* Plot reset now include weather reset
* Added Turkish and Indonesian locales (thanks to POEditor contributors)
* Added /bba removeplot command
* Added new command /bba plotwand
## 5.1.4 - 2026-05-20
### 3.4.1 Release (30.07/03.08.2018)
* Added public access to MySQL executeUpdate method
* Added BBPlayerStatisticChangeEvent event
* Updated Spanish and Korean locales
* Added French locale (thanks to POEditor contributors!)
* Removed scoreboard saving in InventoryManager due to errors
### Changes
### 3.4.0 Release (25/29.07.2018)
* Added super votes
* Added /bb top command
* Fixed locales and updated them
* Added Korean language (thanks to POEditor contributors!)
* Added /bba forcestart <theme> to start with predefined theme (suggested by ColaIan)
- Add a `/hub` command that returns players from BuildBattle lobbies or active games
to the main world spawn.
- Return players to the main world when they reconnect from an arena world, or when
they quit mid-game.
- Clean up arena membership, plot membership, scoreboards, bossbars, action bars,
player visibility and empty-game shutdown when a player leaves via `/hub`.
- Whitelist `hub` by default for in-arena command blocking.
- Show `&4BuildBattle-OG`, the arena name, its state and the player count on default
sign lines.
- Remove external telemetry, custom chart registration, the bundled metrics
implementation and the metrics plugin id.
### 3.3.0 Release (24.07.2018)
* Now while teleporting to the plot you won't fall down
* Fixed xp was given wrong using inventoryView manager
* Removed unnecessary listeners from spectator code
* Use-Name-Instead-Of-UUID-In-Database option was removed, it's no longer supported
* Removed Particle-Offset option, was useless, default offset should stay same for every server
* Removed Disable-Scoreboard-Ingame option as scoreboard is integral part of the game
* Removed Hook-Into-Vault option as plugin automatically hooks with Vault if found
(this hook really doesn't add anything except an extra placeholder on the scoreboard which is anyway medium useful in this game)
* Using item flags instead of empty custom enchant which didn't work in 1.13
* **Added 1.13 support**
(still lots of code uses deprecated code which shouldn't be used in 1.13 but because 1.13 has got backwards compatibility
we will keep that for a while as an temporary workaround)
**Keep in mind that 1.13 forces me to do changes with ID's in BuildBattle and those changes will be done soon**
## 5.1.3 - 2026-04-23
### 3.2.2 Release (20.07.2018)
* Fixed NoSuchMethod error in 1.9.4 for title
* Added support for Vietnamese, Hungarian and Chinese simplified locales
* Added ability to change weather in plot
### Changes
### 3.2.1 Release (14.07.2018)
* Fixed NPE when clicking not named Villager
* Fixed migration error
### 3.2.0 Release (06/12.07.2018)
* Added video tutorial link while creating new arena
* Added new game mode: TEAM
* Fixed error on disabling caused by disabled boss bar feature
* Item rewards at the end of the game now will be properly given after clearing in-game inventoryView of players
* Vote items now look like Hypixel ones
* Worst vote will now count as 1 point not 0 (so every other vote is +1 point now)
* Implemented theme voting feature like hypixel, before game starts players will vote for theme
* Added localization support via POEditor
* Fixed language migration from version 1 (very old)
* Added missing plugin prefixes to some command messages
* Added Spanish locale (thanks to TheLordDarkYT for POEditor contribution!)
* Separate game timer for team mode
### 3.1.2 Release (05.07.2018)
* Fixed error when 1st winner UUID was null (somehow)
* Added subtitle "x seconds left" in game
### 3.1.0 Release (08.06.2018)
* New good looking summary message at the end of the game
* Added game sign block states
* /bb command is now translatable via language.yml
* Admin commands (/bba) are now better with hover and click event (JSON messages)
* Default map name when creating new arena is arena ID not "0" now
* Now warning message "can't save language.yml because already exists!" won't occur anymore
* Fixed error in console when player left the arena and his plot was cleared even if he didn't have it
* Now you can't change your floor by NPC during the voting time
### 3.0.4 Release (04.06.2018)
* Rewards will be given now only once after the game
* Now you can leave started game without spamming infinitely errors in console
* Fixed broken heads lores in heads menu and changed some strings there
* Fixed wrong displayed winners names at the end in summary
* Now sending "You've became xth" message for 4th winners and lower
* Voting for player plot title is now displayed longer
* Added missing plugin prefix in voting messages
* Immediately voting after game timer ends now
### 3.0.2 Release (03.06.2018)
* Fixed /bb create command not working
* Added /bba settheme command
* Fixed game boss bar not removing after plugin force disable
### 3.0.0 Release (14.05.2018 - 01.06.2018)
* Add everything here
- Remove the Plugily Projects service hooks. Upstream's `ServiceRegistry.registerService()`
pinged `https://api.plugily.xyz/ping.php` on enable and constructed `LocaleService`
and `MetricsService`. The override skips the ping and leaves `serviceEnabled=false`,
which also disables:
- remote translation fetching from `api.plugily.xyz/locale/v3/fetch.php`, so the
bundled `Default` locale is used instead;
- automatic error reporting to `api.plugily.xyz/error/report.php`, since
`ReportedException` gates on `isServiceEnabled()`;
- Plugily's internal `MetricsService` timer.
- Replace upstream's `UpdateChecker` with one that returns `UP_TO_DATE` instead of
calling `api.spiget.org`, disabling both the on-enable check and the OP-join
notifier.
- Exclude the upstream `ServiceRegistry` and `UpdateChecker` classes from the shaded
jar so the local overrides win after relocation.
- Fix the head cache.
- Add MyWorlds fork compatibility and backport to the 1.19.4 API.
- Migrate the build from Maven to Gradle and rename the project to BuildBattle-OG.
-33
View File
@@ -1,33 +0,0 @@
## This file is dedicated to **Build Battle** project's all-time contributors.
## **very outdated, please nag me if you still see it here**
**I'm sincerely glad to everyone who supported our project every time!**
**Contributors are listed in alphabetical order, every contributor is equally important!**
* Adrian Garay - Spanish translator
* [Dianox](https://www.spigotmc.org/members/dianox.74931/) - French translator
* Fatih Resul Göker - Turkish translator
* Haoting - Chinese (Simplified) translator
* [HomieDion](https://www.spigotmc.org/members/homiedion.118743/) - code snippets
* HStreamGamer - Vietnamese translator
* [human0324](https://www.spigotmc.org/members/human0324.532201/) - Korean translator
* [inventivetalent](https://www.spigotmc.org/members/inventivetalent.6643/) - code snippets
* Ito - Indonesian translator
* [Marcely99](https://www.spigotmc.org/members/marcely99.62672/) - code snippets
* [MattUGV](https://www.spigotmc.org/members/mattugv.139086/) - code snippets
* [montlikadani](https://www.spigotmc.org/members/toldi.251100/) - Hungarian translator and code contributor
* Pheonix Harryson - Korean translator
* [Tigerkatze](https://www.spigotmc.org/members/tigerkatze.414545/) - Main tester, German translator and staff member of Plajer's Lair discord
* [TomTheDeveloper](https://www.spigotmc.org/members/tomthedeveloper.4729/) - former author of Build Battle 1 and 2
* [Tristiisch74](https://www.spigotmc.org/members/tristiisch74.149406/) - code snippets
**Thanks to these companies for providing free licenses for Build Battle open source work:**
* Code Whale Inc. - POEditor open source project license
**Also thanks to every bug reporters for reporting us those nasty bugs, and code contributors for making Build Battle better!**
`Please note that translators are put here only if their contribution to the language is higher than 15% of total strings`
![](https://i.imgur.com/LFakRC8.png)
+14 -54
View File
@@ -1,3 +1,15 @@
# License
BuildBattle-OG - Ultimate building competition minigame.
Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program below. If not, see <http://www.gnu.org/licenses/>.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
@@ -481,8 +493,8 @@ by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
patent sublicenses in a manner consistent with the requirements of this
License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
@@ -620,55 +632,3 @@ copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+370
View File
@@ -0,0 +1,370 @@
# BuildBattle-OG
TrueOG Network's fork of [Plugily-Projects/BuildBattle](https://github.com/Plugily-Projects/BuildBattle) — a
building competition minigame for Purpur `1.19.4`, using `MyWorlds` for arena world management.
Current version: `5.1.12` ([changelog](CHANGELOG.md)).
Two game modes ship in the box. In **classic** mode players build on their own plot against a theme, then vote
on each other's builds. In **Guess The Build** one player builds while everyone else races to guess the theme
in chat for points.
## OG fork notes
This fork makes no outside service calls. Upstream's update checker, remote translation fetching, error
reporting and metrics are all stubbed out, so the bundled `Default` locale is always used and nothing phones
home. It also adds `/hub`, `/bbjoin`, `/bbforcestart` and reconnect handling so players reliably get back to
the main world from an arena, and integrates with the rest of the TrueOG plugin set (see
[Integrations](#integrations)).
Return locations are recorded whenever a player enters an arena world by any route — `/bbjoin`, `/bb join`, a
portal, or `/mw tp` — and are kept on disk, so `/hub`, a relog, a respawn or a server restart all put the
player back where they started rather than at main world spawn.
`/v` and `/vote` are claimed inside BuildBattle worlds before any other plugin sees them, so VotingPlugin
cannot take the `/vote` label away from theme voting. BuildBattle has no map pool to vote on, so the command
drives the theme poll the vote menu already owns rather than adding a second one.
`/hub`, `/lobby` and `/spawn` are claimed the same way inside BuildBattle worlds. Splegg-OG and
TheHerobrine-OG register `/hub` too, and Bukkit gives the bare label to whichever plugin loads first, so
without the claim an arena player's `/hub` could run another minigame's command and teleport them out while
the arena still counted them; Spawn-OG's `/spawn` did the same. All three now leave the arena properly and
return the player to where they came from.
Every arena is its own lobby with its own hub world (`BB1-hub`, `BB2-hub`, ...). `/bb join` and `/bbjoin`
with no lobby list them all with a clickable join line, like `/hbjoin`; `/bb join BB2` or `/bb join 2` joins
one directly.
## Requirements
- Purpur `1.19.4`
- `MyWorlds` (either the `MyWorlds` or the `My_Worlds` fork — both plugin names are accepted)
- `BKCommonLib` (MyWorlds' own dependency)
Optional, integrated when present: `Utilities-OG`, `Chat-OG`, `Scoreboard-OG`, `GameModeInventories-OG`,
`Spawn-OG`, `Citizens`, `PlaceholderAPI`, `ViaVersion`.
## Quick Setup
The bundled `arenas.yml` ships arena `BB1` fully configured for the open source TrueOG maps, and the
bundled `config.yml` already protects `world`, `world_nether` and `world_the_end`. What is left is
putting the two worlds in place:
1. Fetch the maps from the [true-og repository](https://git.trueog.net/trueog/true-og) (`maps/`) and put
`Plaza` and `BB1_Hub` under `<server root>/maps/`, the same directory Splegg-OG and TheHerobrine-OG use
(`MyWorlds.Map-Base` in `config.yml`). See [Bundled maps](#bundled-maps).
2. Drop the jar in `plugins/` and start the server. On every boot the plugin copies each arena world from
`maps/` to the server root under its world name (`BB1-map` from `Plaza` via the arena's `mapname`,
`BB1-hub` from `BB1_Hub`), pins its void generator and loads it through MyWorlds; nothing has to be
registered by hand. Worlds live at the server root only as disposable copies.
3. `/bb join BB1` (`/bb join` alone lists the lobbies).
A world with no map under `maps/` is loaded from the server root as before, but never generated: an arena
whose world is missing from both places is skipped with an error in the console instead of being handed
a freshly generated vanilla world.
Only if your main worlds are not named `world`, `world_nether` and `world_the_end`: list them under
`MyWorlds.Protected-Worlds` in `config.yml` so arenas can never be created there.
To build your own arena instead, or to add a second concurrent lobby with its own `BB2-hub` and `BB2-map`
worlds: `/bba setup create <arena>` opens the setup inventory for the lobby, start and end locations,
`/bba addplot <arena>` marks each build plot with the location wand, `/bba settheme <theme>` overrides the
bundled `themes.yml` list, and `/bba setup edit <arena>` reopens the inventory later. Optionally place join
signs in the hub so players can join without commands (see [Join Signs](#join-signs)).
## Bundled maps
Both maps are maintained in the [true-og repository](https://git.trueog.net/trueog/true-og) under `maps/`,
which is also where the server keeps them (`MyWorlds.Map-Base`), and are the canonical worlds for the
shipped `BB1` arena:
| Map | Server world | License | Notes |
|---|---|---|---|
| `Plaza` | `BB1-map` | Unlicense (public domain) | Twelve 31x31 plots (y 64 to 96) in a ring around a 41x41 plaza, floating in the void. Generated by `Plaza/tools/gen_plaza.py`, so it can be regenerated or resized. |
| `BB1_Hub` | `BB1-hub` | CC BY-SA 3.0, Green Leave Lobby by Libers97 | Same lobby build as `SP1_Hub` and `HB1_Hub`; spawn at `-3, 64, 1`. |
The shipped `arenas.yml` lists the twelve plot cuboids, the plaza centre (`0.5, 65, 0.5`) as start and
spectator location, and the hub spawn as lobby and end location, with `maximumplayers: 12` (one plot per
player). Plot floors are regenerated from the cuboid's lowest layer with `Floor.Material` on every reset;
Plaza's oak floors match the default `log`, and its frames and pedestals sit outside the cuboids so they
survive resets. Keep both worlds out of GameModeInventories-OG's `restrict_adventure_worlds` and Spawn-OG's
`login-safety.worlds`.
The server-root copies are rebuilt from `maps/` on every start, so in-game edits to an arena world do not
survive a restart; to change a map, replace the files under `maps/<Name>/`. Chunks outside the saved
region generate as void through the bundled `BuildBattle-OG:void` generator, which the plugin pins onto
each arena world in MyWorlds' `worlds.yml` unless one is already set (`MyWorlds.Void-Generator`).
## Join Signs
Admins can place physical signs that players right-click to join an arena. Signs render the four lines from
`Signs.Lines` in `language.yml` (title, arena name, game state, player counts) and update automatically. With
`Sign-Block-States: true` in `config.yml`, the block behind the sign also changes color with the game state
(white waiting, yellow starting, orange in game, gray ending, black restarting).
To set one up:
1. Make sure the arena exists (`/bba setup create <arena>`, see Quick Setup above).
2. Place a sign in a persistent world such as the server hub — not in the `BB<n>-map`/`BB<n>-hub` worlds,
which are recreated between games.
3. Write `[buildbattle]` on the first line and the arena id (e.g. `BB1`) on the second line. Requires the
`buildbattle.admin.sign.create` permission.
4. The sign reformats immediately; right-clicking it joins that arena.
Sign locations are saved under the arena's `signs:` list in `arenas.yml`. Breaking a registered sign requires
`buildbattle.admin.sign.break` and removes it from the arena.
## World naming
Arena worlds must be named `BB<n>-<map>` and their lobby worlds `BB<n>-hub`, for example `BB1-map` and
`BB1-hub`. Chat-OG resolves a world to a multi-world game by that `<letters><digits>-` prefix and keys its
per-game Discord channel off it, so the `BB` prefix must also exist under `discord.games` in **Chat-OG's**
`config.yml`. Worlds named any other way simply stay in global chat — everything else still works.
Arena ids follow the same convention, so the arena that owns `BB1-hub` and `BB1-map` is named `BB1`. `/bbjoin`
accepts the id case-insensitively and also accepts the bare number, so `/bbjoin BB1`, `/bbjoin bb1` and
`/bbjoin 1` are the same command. A bare number that matches more than one arena is refused rather than
guessed.
> **Upgrading from 5.1.4 or earlier:** the bundled `arenas.yml` template changed from `bb_lobby` / `bb_game_1`
> to `BB1-hub` / `BB1-map`, and its arena id from `default` to `BB1`. Existing arenas keep whatever names they
> already have; changing the template does not migrate them. To adopt the convention: stop the server, rename
> the world folders, then update the arena id, the three location lines and `world:` in `arenas.yml` along with
> your MyWorlds `worlds.yml` and `inventories.yml` entries. Until the worlds are renamed, `/bbjoin <number>`
> cannot resolve the arena and no chat formatter is registered.
## Configuration
`config.yml` holds the fork-specific `MyWorlds` block:
```yaml
MyWorlds:
# Applied to MyWorlds at runtime on startup; MyWorlds' own config.yml is never rewritten.
Enable-World-Inventories: true
Enable-World-Chat: true
# BuildBattle arenas, plots and lobby locations are blocked from these worlds.
Protected-Worlds:
- world
- world_nether
- world_the_end
# Days to keep a player's pre-arena return location on disk (0 = keep forever).
PreJoin-Location-Expiry-Days: 30
# Cold-storage map directory, relative to the server root (absolute paths accepted, empty disables).
# Each arena world is copied from <Map-Base>/<Name>/ to the server root and loaded on every boot.
Map-Base: 'maps'
# Pin the bundled void generator onto every arena world so unsaved chunks stay void.
Void-Generator: true
```
Classic and Teams matches run in rounds, set per mode under `Time-Manager` in `config.yml`:
```yaml
Time-Manager:
Classic:
# Build rounds per match; each round gets its own theme and plot vote, points add up.
Rounds: 3
# Pick each round's theme at random from themes.yml instead of holding a vote.
Random-Theme: true
Voting:
# Total time of voting for themes before starting
Theme: 25
# Total time of voting per player plot
Plot: 15
# Build time per round
In-Game: 150
```
Each round announces its theme (drawn at random from the mode's list in `themes.yml`, or voted on for
`Voting.Theme` seconds when `Random-Theme` is off; a theme is never repeated within a match), runs the build
clock, then walks every plot for a vote. Plots are wiped between rounds, votes add up across them, and the
highest total after the last round wins. `Rounds: 1` is the single-build upstream flow.
While building, each player is held to their plot plus a grace margin (`Plot.Border` in `config.yml`):
```yaml
Plot:
# Wall around the plot a player is building in, shown only to them; the world is never changed.
Border:
# Draw the wall. Off, the limit below still holds and a builder past it is pulled back.
Enabled: true
# Blocks a builder may step outside the plot before the wall.
Grace: 3
# Wall blocks within this many blocks of the builder are drawn.
Distance: 8
# RAINBOW_GLASS, RAINBOW_WOOL, RAINBOW_TERRACOTTA, RAINBOW_CONCRETE or any block name.
Block: RAINBOW_GLASS
```
The wall is the one-block shell just outside that margin, sent to the builder as client-side block
changes (`Player#sendMultiBlockChange`) and restored as they move away, so nothing in the world changes
and nobody else sees it. It is drawn during build time only, on all six faces, and skips real solid blocks.
A move that would still end beyond the wall is cancelled, and anyone found past it by any other route
(a teleport, a vehicle) is pulled to the nearest legal spot at their own height, or to the plot spawn
when that spot is blocked. `Plot.Move-Outside: true` turns the whole thing off.
Arenas live in `arenas.yml`:
```yaml
instances:
BB1:
lobbylocation: BB1-hub,-1.0,80.0,7.0,0.0,0.0
startlocation: BB1-map,-1.0,80.0,7.0,0.0,0.0
endlocation: BB1-hub,-1.0,80.0,7.0,0.0,0.0
minimumplayers: 2
maximumplayers: 10
plotmembersize: 1
mapname: mapname
world: BB1-map
# classic (deprecated: solo), guess_the_build
gametype: classic
isdone: false
signs: {}
plots: {}
```
Themes are in `themes.yml`, messages in `language.yml`, and per-player statistics use `mysql.yml` when
`Database.Enabled` is on.
The boss bar is a timer for the current phase: its title names the phase with a `mm:ss` clock and
`true-og.net`, its colour follows the phase, and it drains as the phase runs out. `Bossbar.Display` in
`config.yml` turns it off; the `Bossbar` lists in `language.yml` are not read.
## Placeholders
Registered through Utilities-OG as MiniPlaceholders, resolved for the viewing player, and updated the
moment a game's points are awarded:
| Placeholder | Value |
|-------------|-------|
| `<bb_score>` | The player's `POINTS_TOTAL` |
| `<bb_rank>` | Colored rank name for that score: Apprentice (0), Builder (100), Bricklayer (300), Carpenter (750), Mason (1,500), Craftsman (3,000), Architect (6,000), Engineer (10,000), Sculptor (15,000), Master Builder (25,000), Forger (40,000), Dreamer (60,000), Extractor (100,000), Dom (150,000); Dreamweaver for the top player once they also reach Dom |
## Integrations
| Plugin | Effect when installed |
|--------|-----------------------|
| `MyWorlds` / `My_Worlds` | **Required.** Arena world management, per-world inventories and chat. |
| `Utilities-OG` | Registers the `<bb_score>` and `<bb_rank>` [placeholders](#placeholders). `language.yml` values containing a MiniMessage tag or the `&*` rainbow code render through TrueOG's colorizer, enabling `<#rrggbb>` hex, `<gradient:...>`, named colours and decorations. Plain `&`-coded values are passed through byte-for-byte, so nothing shipped changes appearance. Without the plugin, all values keep their default formatting. |
| `Chat-OG` | Arena chat is scoped per world, styled by BuildBattle-OG's own formatter, and mirrored to the game's Discord channel, provided worlds follow the [naming convention](#world-naming) and `discord.games.BB` exists in Chat-OG's config. The formatter shows the player count in the lobby, `VOTE` and `JUDGING` during the voting phases, and the theme while building — never in Guess The Build, where the theme is the answer. |
| `Scoreboard-OG` | With `1.2.0` or newer, the arena sidebar is drawn through Scoreboard-OG's sidebar API instead of MiniGamesBox's packet board. The network board returns on its own when the player leaves the arena, and `/togglescoreboard` is honoured. Older builds, or no Scoreboard-OG at all, keep the MiniGamesBox board. Both draw the same code-built card in the TrueOG style (`♥ BuildBattle-OG ♥` title, blank-separated blocks, `true-og.net` footer) with every line within 16 legacy characters for 1.8 clients; only `Scoreboard.Title` and `Scoreboard.Theme-Unknown` in `language.yml` are still read. |
| `GameModeInventories-OG` | Its inventory swap is suspended for everyone inside arena worlds, by any route in, and for one tick after leaving, so the survival inventory is never filed under an arena gamemode. Builders additionally get a creative exemption scoped to arena worlds at runtime. Do **not** grant regular players `gamemodeinventories.toggle` or `gamemodeinventories.anywhere`, and keep arena worlds **out** of `restrict_adventure_worlds` — guessers are put in adventure mode. |
| `Spawn-OG` | Keep arena worlds **out** of its `login-safety.worlds` list so reconnect handling stays with BuildBattle-OG. |
| `VotingPlugin` | Keeps `/vote` and `/v` everywhere outside BuildBattle worlds; BuildBattle-OG never declares either label in plugin.yml. |
| `Citizens` | Enables `/bba addnpc` for plot NPCs. |
| `PlaceholderAPI` | Exposes arena placeholders to other plugins. |
## Commands
`/bb` (aliases `buildbattle`, `buildb`) and `/bba` (aliases `buildbattleadmin`, `buildbadmin`) each print
their own help listing. The tables below cover the arguments this fork defines plus the most-used ones
inherited from MiniGamesBox.
### Player Commands
| Command | Permission | Description |
|---------|------------|-------------|
| `/bb join [lobby]` | — | Join a lobby by id (`BB1`, or just `1`); no argument lists the lobbies with clickable join lines |
| `/bbjoin [lobby]` | — | The same as `/bb join` |
| `/hub`, `/lobby`, `/spawn` | — | Leave the arena and return to where you came from, or to main spawn |
| `/bb randomjoin` | — | Join any arena with room |
| `/vote [#]` or `/v [#]` | — | List the themes up for voting and cast a vote |
| `/bb leave` | — | Leave the current arena |
| `/bb arenas` | `buildbattle.arenas` | Open the arena selector |
| `/bb menu` | — | Open the plot options menu |
| `/bb guess <word>` | — | Submit a Guess The Build guess |
| `/bb selectplot` | `buildbattle.command.selectplot` | Select the plot you are standing in |
| `/bb stats` | — | Show your statistics |
| `/bb top [statistic]` | — | Show the leaderboard |
| `/hub` | — | Leave the arena or lobby and return to the main world |
### Admin Commands
| Command | Permission | Description |
|---------|------------|-------------|
| `/bba setup create <arena>` | `buildbattle.admin.setup` | Create a new arena |
| `/bba setup edit <arena>` | `buildbattle.admin.setup` | Open the arena setup inventory |
| `/bba delete <arena>` | `buildbattle.admin.delete` | Delete an arena |
| `/bba list` | `buildbattle.admin.list` | List arenas and their states |
| `/bba reload` | `buildbattle.admin.reload` | Reload configuration |
| `/bba stop` | `buildbattle.admin.stop` | Stop the running game |
| `/bbforcestart [time]` | `buildbattle.admin.forcestart` | Start the game ignoring `minimumplayers` |
| `/bba forcestart` | `buildbattle.admin.forcestart` | Force the game to start |
| `/bba forceplay <arena> <theme>` | `buildbattle.admin.forceplay` | Force an arena to play a theme |
| `/bba settheme <theme>` | `buildbattle.admin.settheme` | Set the current arena's theme |
| `/bba theme [add/remove] [gameType] [theme]` | `buildbattle.admin.theme` | Manage the theme list |
| `/bba addplot <arena>` | `buildbattle.admin.addplot` | Add a build plot using the location wand |
| `/bba removeplot <arena> <plot ID>` | `buildbattle.admin.removeplot` | Remove a build plot |
| `/bba addnpc` | `buildbattle.admin.addnpc` | Place a plot NPC (requires Citizens) |
| `/bba locwand` | `buildbattle.admin.locwand` | Get the plot selection wand |
| `/bba tp <arena/worldName> [location type]` | `buildbattle.admin.teleport` | Teleport to an arena location |
| `/bba spychat` | `buildbattle.admin.spychat` | Toggle arena chat spying |
| `/bba statistic <adjust/set> <statistic> <amount> [player]` | `buildbattle.admin.statistic` | Adjust a player's statistic (`buildbattle.admin.statistic.others` for `[player]`) |
## Permissions
### Administration
`buildbattle.admin.*` (default OP) grants every node in the Admin Commands table above, plus:
| Permission | Default | Description |
|------------|---------|-------------|
| `buildbattle.admin` | OP | Base administrative access |
| `buildbattle.admin.sign.create` | OP | Create BuildBattle join signs |
| `buildbattle.admin.sign.break` | OP | Break BuildBattle join signs |
| `buildbattle.admin.statistic.others` | OP | Adjust another player's statistics |
| `buildbattle.admin.locale` / `.locales` | OP | Inspect and switch locales |
| `buildbattle.admin.kitfile` | OP | Manage kit files |
| `buildbattle.admin.placeholders` | OP | Check placeholder resolution |
| `buildbattle.admin.leaderboard.manage` | OP | Manage leaderboard holograms |
| `buildbattle.command.override` | OP | Bypass in-game command blocking (`Block.In-Game.Commands`) |
| `buildbattle.updatenotify` | OP | Update notifications (inert in this fork) |
### Gameplay
| Permission | Default | Description |
|------------|---------|-------------|
| `buildbattle.command.selectplot` | OP | Select the plot you are standing in |
| `buildbattle.particles` | OP | Use the particle menu |
| `buildbattle.heads` | OP | Use the player-heads menu (set per entry in `heads/mainmenu.yml`) |
| `buildbattle.arenas` | OP | Open the arena selector |
| `buildbattle.fullgames` | OP | Join arenas that are already full |
| `buildbattle.join.<arena>` | OP | Join a specific arena, when per-arena join permissions are enabled |
Point, voting and experience multipliers are configured by permission node in `permissions.yml`. Biome menu
entries use `biomes.VIP` by default, configurable in `biomes.yml`.
## Building
```bash
git clone --recursive https://git.trueog.net/trueog/BuildBattle-OG
cd BuildBattle-OG
./gradlew build
```
If you cloned without `--recursive`, run `./bootstrap.sh` first. The shaded plugin jar lands in
`build/libs/BuildBattle-OG-<version>.jar`.
# Credits
BuildBattle-OG is a fork of [Plugily-Projects/BuildBattle](https://github.com/Plugily-Projects/BuildBattle) by
Tigerpanzer_02, Plajer, TomTheDeveloper and contributors, distributed under the GPLv3.
## Open Source Libraries
| Library | Author | License |
|-------------------------------------------------------------|-------------------------------------------------------|------------------------------------------------------------------------------------|
| [InventoryFramework](https://github.com/stefvanschie/IF/) | [stefvanschie](https://github.com/stefvanschie) | [Unlicense](https://github.com/stefvanschie/IF/blob/master/LICENSE) |
| [ScoreboardLib](https://github.com/TigerHix/ScoreboardLib/) | [TigerHix](https://github.com/TigerHix) | [LGPLv3](https://github.com/TigerHix/ScoreboardLib/blob/master/LICENSE) |
| [HikariCP](https://github.com/brettwooldridge/HikariCP) | [brettwooldridge](https://github.com/brettwooldridge) | [Apache License 2.0](https://github.com/brettwooldridge/HikariCP/blob/dev/LICENSE) |
| [Commons Box](https://github.com/Plajer/Commons-Box) | [Plajer](https://github.com/Plajer) | [GPLv3](https://github.com/Plajer/Commons-Box/blob/master/LICENSE.md) |
The plot wall (`PlotBorderManager`) is derived from the border module of
[EternalCombat](https://github.com/EternalCodeTeam/EternalCombat) by the EternalCode Team, by way of the
TrueOG [Duels-OG](https://git.trueog.net/trueog/Duels-OG) adaptation. Both are licensed under the
[Apache License 2.0](https://github.com/EternalCodeTeam/EternalCombat/blob/master/LICENSE); the file keeps
that notice and lists the changes made.
## Attributions
Thanks to Code Whale for the Open Source POEditor license behind upstream's locales, and to
[Minecraft Heads](https://minecraft-heads.com/) for the head names and textures used in the heads menu.
Executable
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/bash
# Fetch all submodule content.
git submodule update --force --recursive --init
+205
View File
@@ -0,0 +1,205 @@
/* ------------------------------ Plugins ------------------------------ */
plugins {
id("java") // Import Java plugin.
id("java-library") // Import Java Library plugin.
id("com.diffplug.spotless") version "8.1.0" // Import Spotless plugin.
id("com.gradleup.shadow") version "8.3.9" // Import Shadow plugin.
id("checkstyle") // Import Checkstyle plugin.
eclipse // Import Eclipse plugin.
}
extra["kotlinAttribute"] = Attribute.of("kotlin-tag", Boolean::class.javaObjectType)
val kotlinAttribute: Attribute<Boolean> by rootProject.extra
/* --------------------------- JDK / Kotlin ---------------------------- */
java {
sourceCompatibility = JavaVersion.VERSION_17 // Compile with JDK 17 compatibility.
toolchain { // Select Java toolchain.
languageVersion.set(JavaLanguageVersion.of(17)) // Use JDK 17.
vendor.set(JvmVendorSpec.GRAAL_VM) // Use GraalVM CE.
}
}
/* ----------------------------- Metadata ------------------------------ */
group = "plugily.projects"
version = "5.1.12"
description = "BuildBattle-OG" // Declare plugin description.
val apiVersion = "1.19" // Declare minecraft server target version.
// Harvest every upstream license shipped alongside a vendored jar in libs/, so adding a library does
// not also require editing this file.
val vendoredLicenseFiles =
fileTree("libs") {
include("**/LICENSE", "**/LICENSE.*", "**/License", "**/License.*", "**/COPYING", "**/COPYING.*")
include("**/NOTICE", "**/NOTICE.*")
exclude("**/build/**", "**/.git/**")
}
/* ----------------------------- Resources ----------------------------- */
tasks.named<ProcessResources>("processResources") {
val props = mapOf("version" to version, "apiVersion" to apiVersion)
inputs.properties(props) // Indicates to rerun if version changes.
filesMatching("plugin.yml") { expand(props) }
from("LICENSE.md") { into("/") } // Bundle licenses into jarfiles.
}
/* ---------------------------- Repos ---------------------------------- */
repositories {
mavenCentral() // Import the Maven Central Maven Repository.
maven("https://ci.mg-dev.eu/plugin/repository/everything/") // BKCommonLib.
gradlePluginPortal() // Import the Gradle Plugin Portal Maven Repository.
maven { url = uri("https://repo.purpurmc.org/snapshots") } // Import the PurpurMC Maven Repository.
maven { url = uri("file://${System.getProperty("user.home")}/.m2/repository") }
System.getProperty("SELF_MAVEN_LOCAL_REPO")?.let { // TrueOG Bootstrap mavenLocal().
val dir = file(it)
if (dir.isDirectory) {
println("Using SELF_MAVEN_LOCAL_REPO at: $it")
maven { url = uri("file://${dir.absolutePath}") }
} else {
logger.error("TrueOG Bootstrap not found, defaulting to ~/.m2 for mavenLocal()")
mavenLocal()
}
} ?: logger.error("TrueOG Bootstrap not found, defaulting to ~/.m2 for mavenLocal()")
maven { url = uri("https://maven.plugily.xyz/releases") }
maven { url = uri("https://maven.plugily.xyz/snapshots") }
maven { url = uri("https://repo.citizensnpcs.co/") }
maven { url = uri("https://jitpack.io") }
}
/* ---------------------- Java project deps ---------------------------- */
dependencies {
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Declare Purpur API version to be packaged.
compileOnly("org.jetbrains:annotations:23.0.0")
compileOnly(project(":libs:MyWorlds")) // Import MyWorlds API (git submodule, built from source).
compileOnly(
"com.bergerkiller.bukkit:BKCommonLib:1.19.4-v2"
) // Import BKCommonLib API from its Maven repository (required by MyWorlds at compile time).
compileOnly("net.citizensnpcs:citizensapi:2.0.26-SNAPSHOT") {
exclude(group = "ch.ethz.globis.phtree", module = "phtree")
}
// Import TrueOG Network Utilities-OG Java API (from source), used for TrueOG color/gradient rendering.
// NEVER promote this to implementation: Utilities-OG shades the Kotlin stdlib and coroutines, and with
// isEnableRelocation = true below they would be rewritten under plugily.projects.shadow.* and break at
// runtime. compileOnly/compileOnlyApi stay off runtimeClasspath, so Shadow never bundles or relocates them.
compileOnlyApi(project(":libs:Utilities-OG"))
compileOnly(
files("libs/Chat-OG/Chat-OG.jar")
) // Import Chat-OG API for world chat formatting (vendored jar until the API lands in trueog/Chat-OG).
compileOnly(project(":libs:Scoreboard-OG")) // Import TrueOG Network Scoreboard-OG Java API (from source).
implementation("plugily.projects:MiniGamesBox-Classic:1.4.5")
implementation("org.slf4j:slf4j-api:2.0.17") // Bundle a relocated SLF4J API for shaded dependencies.
implementation("org.slf4j:slf4j-nop:2.0.17") // Provide a relocated no-op SLF4J backend to avoid provider warnings.
testImplementation("org.junit.jupiter:junit-jupiter:5.13.3") // Add JUnit API to testing environment.
// compileOnly/compileOnlyApi do not propagate to the test classpath, so restate what the tests need.
testImplementation("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Adventure lives here.
testImplementation(project(":libs:Utilities-OG")) // The colorizer under test.
testRuntimeOnly("org.junit.platform:junit-platform-launcher") // Add JUnit engine to the testing runtime.
}
apply(from = "eclipse.gradle.kts") // Import eclipse classpath support script.
/* ---------------------- Reproducible jars ---------------------------- */
tasks.withType<AbstractArchiveTask>().configureEach { // Ensure reproducible .jars
isPreserveFileTimestamps = false
isReproducibleFileOrder = true
}
/* ----------------------------- Shadow -------------------------------- */
tasks.shadowJar {
exclude("io.github.miniplaceholders.*") // Exclude the MiniPlaceholders package from being shadowed.
exclude("plugily/projects/minigamesbox/classic/utils/services/locale/LocaleService.class")
exclude("plugily/projects/minigamesbox/classic/utils/services/locale/LocaleService$*.class")
exclude("plugily/projects/minigamesbox/classic/utils/services/ServiceRegistry.class")
exclude("plugily/projects/minigamesbox/classic/utils/services/metrics/Metrics.class")
exclude("plugily/projects/minigamesbox/classic/utils/services/metrics/Metrics$*.class")
exclude("plugily/projects/minigamesbox/classic/utils/services/metrics/MetricsService.class")
exclude("plugily/projects/minigamesbox/classic/utils/services/metrics/MetricsService$*.class")
exclude("plugily/projects/minigamesbox/classic/utils/services/UpdateChecker.class")
exclude("plugily/projects/minigamesbox/classic/utils/services/UpdateChecker$*.class")
from("LICENSE.md") {
into("META-INF/licenses/BuildBattle-OG")
includeEmptyDirs = false
}
from(vendoredLicenseFiles) {
into("META-INF/licenses/libs")
includeEmptyDirs = false
}
isEnableRelocation = true
relocationPrefix = "${project.group}.shadow"
relocate("com.zaxxer.hikari", "plugily.projects.buildbattle.database.hikari")
relocate("plugily.projects.minigamesbox", "plugily.projects.buildbattle.minigamesbox")
archiveClassifier.set("") // Use empty string instead of null.
// Relocate the SLF4J provider registration with SLF4J itself; the other service files keep their current form.
mergeServiceFiles { setIncludes(listOf("META-INF/services/org.slf4j.spi.SLF4JServiceProvider")) }
minimize {
// SLF4J discovers providers through META-INF/services, so Shadow's static minimizer cannot see this usage.
exclude(dependency("org.slf4j:slf4j-nop:.*"))
}
}
tasks.jar { archiveClassifier.set("part") } // Applies to root jarfile only.
tasks.build { dependsOn(tasks.spotlessApply, tasks.shadowJar) } // Build depends on spotless and shadow.
/* --------------------------------- Testing ---------------------------- */
tasks.withType<Test>().configureEach {
useJUnitPlatform() // Enable testing with JUnit 5.
}
/* --------------------------- Javac opts ------------------------------- */
tasks.withType<JavaCompile>().configureEach {
options.compilerArgs.add("-parameters") // Enable reflection for java code.
options.isFork = true // Run javac in its own process.
options.compilerArgs.add("-Xlint:deprecation") // Trigger deprecation warning messages.
options.encoding = "UTF-8" // Use UTF-8 file encoding.
}
/* ----------------------------- Auto Formatting ------------------------ */
spotless {
java {
eclipse().configFile("config/formatter/eclipse-java-formatter.xml") // Eclipse java formatting.
leadingTabsToSpaces() // Convert leftover leading tabs to spaces.
removeUnusedImports() // Remove imports that aren't being called.
}
kotlinGradle {
ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } // JetBrains Kotlin formatting.
target("build.gradle.kts", "settings.gradle.kts") // Gradle files to format.
}
}
checkstyle {
toolVersion = "10.18.1" // Declare checkstyle version to use.
configFile = file("config/checkstyle/checkstyle.xml") // Point checkstyle to config file.
isIgnoreFailures = true // Don't fail the build if checkstyle does not pass.
isShowViolations = true // Show the violations in any IDE with the checkstyle plugin.
}
tasks.named("compileJava") {
dependsOn("spotlessApply") // Run spotless before compiling with the JDK.
}
tasks.named("spotlessCheck") {
dependsOn("spotlessApply") // Run spotless before checking if spotless ran.
}
/* ------------------------------ Eclipse SHIM ------------------------- */
// This can't be put in eclipse.gradle.kts because Gradle is weird.
// Qualifying subproject names keeps :libs:Utilities-OG from colliding with the standalone
// Utilities-OG project that also lives in the Eclipse workspace.
subprojects {
// ":libs" is only an implicit container created by include(":libs:Utilities-OG"). Applying the
// Java plugin to it produced a junk libs/build/libs/libs-BuildBattle-OG.jar next to the vendored
// dependency directories.
if (project.path == ":libs") {
return@subprojects
}
apply(plugin = "java-library")
apply(plugin = "eclipse")
eclipse.project.name = "${project.name}-${rootProject.name}"
tasks.withType<Jar>().configureEach { archiveBaseName.set("${project.name}-${rootProject.name}") }
}
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
<property name="severity" value="error"/>
</module>
<module name="TreeWalker">
<module name="FinalLocalVariable"/>
<module name="AvoidStarImport"/>
<module name="Indentation">
<property name="severity" value="ignore"/>
</module>
</module>
<module name="RegexpSingleline">
<property name="format" value="\borg\.junit\.jupiter\.api\.Assertions\.fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="ignoreCase" value="true"/>
<property name="severity" value="warning"/>
</module>
<module name="RegexpSingleline">
<property name="format" value="(?&lt;!\w)fail\s*\(\s*&quot;Not yet implemented&quot;\s*\)\s*;"/>
<property name="message" value="Remove placeholder fail() and implement the test."/>
<property name="severity" value="warning"/>
</module>
</module>
+404
View File
@@ -0,0 +1,404 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="23">
<profile kind="CodeFormatterProfile" name="TrueOG Network Formatting" version="23">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case_after_arrow" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.align_arrows_in_switch_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="20"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line_on_wrap"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>
+151
View File
@@ -0,0 +1,151 @@
/* Eclipse IDE classpath plumbing. Shared across TrueOG plugin repos. */
import org.gradle.plugins.ide.eclipse.model.EclipseModel
import java.nio.file.Files
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
val kotlinAttribute: Attribute<Boolean> by rootProject.extra
val kotlinPluginProjects = configurations
.getByName("compileClasspath")
.allDependencies
.filterIsInstance<ProjectDependency>()
.filter { it -> it.attributes.getAttribute(kotlinAttribute) != null }
.map { it.path }
kotlinPluginProjects.forEach { evaluationDependsOn(it) }
val ideLibs: Configuration by
configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
}
configure<EclipseModel> {
project {
name = "BuildBattle-OG-Plugin"
}
classpath {
plusConfigurations.add(ideLibs)
}
}
val ideLibDir = layout.buildDirectory.dir("ide-libs")
val hashRegex = Regex("-[0-9a-fA-F]{10}(?=\\.jar$)") // Black magic.
val copyTasks = mutableListOf<TaskProvider<Copy>>()
kotlinPluginProjects.forEach { path ->
val sub = project(path)
val shadowJarProv = sub.tasks.named("shadowJar")
val copyTask =
tasks.register<Copy>("ideCopy${sub.name.replaceFirstChar(Char::titlecase)}") {
dependsOn(shadowJarProv)
from(shadowJarProv)
into(ideLibDir)
rename { it.replace(hashRegex, "") } // Remove git commit hash from jarfile.
}
copyTasks += copyTask
}
/* Ensure the jars exist before .classpath is generated */
tasks.named("eclipseClasspath").configure { dependsOn(copyTasks) }
/* Supply those jars to the ideLibs configuration (after evaluation) */
afterEvaluate { dependencies { add("ideLibs", fileTree(ideLibDir) { include("*.jar") }) } }
val injectIdeLibs =
tasks.register("injectIdeLibs") {
dependsOn("eclipse") // run after all eclipse files are generated
doLast {
val cpFile = file(".classpath")
if (!cpFile.exists()) return@doLast
val jars = fileTree(ideLibDir.get()) { include("*.jar") }.files.sortedBy { it.name }
if (jars.isEmpty()) return@doLast
// Parse DOM
val dbf = DocumentBuilderFactory.newInstance()
val doc = dbf.newDocumentBuilder().parse(cpFile)
val root = doc.documentElement
// Helper to see if an entry already exists
fun exists(path: String): Boolean =
root.getElementsByTagName("classpathentry").let { list ->
(0 until list.length).any { i ->
val n = list.item(i)
val kind = n.attributes?.getNamedItem("kind")?.nodeValue
val p = n.attributes?.getNamedItem("path")?.nodeValue
kind == "lib" && p == path
}
}
// Remove any entry that points to ide-libs dir (folder or jars) to avoid dupes
val toRemove = mutableListOf<org.w3c.dom.Node>()
val list = root.getElementsByTagName("classpathentry")
val dirPath = ideLibDir.get().asFile.absolutePath
for (i in 0 until list.length) {
val n = list.item(i)
val kind = n.attributes?.getNamedItem("kind")?.nodeValue
val p = n.attributes?.getNamedItem("path")?.nodeValue ?: ""
if (kind == "lib" && (p == dirPath || p.startsWith("$dirPath/"))) {
toRemove += n
}
}
toRemove.forEach { root.removeChild(it) }
// Append our jar entries LAST
jars.forEach { f ->
val abs = f.absolutePath
if (!exists(abs)) {
val entry = doc.createElement("classpathentry")
entry.setAttribute("kind", "lib")
entry.setAttribute("path", abs)
root.appendChild(entry)
}
}
// Write back pretty
val tf =
TransformerFactory.newInstance().newTransformer().apply {
setOutputProperty(OutputKeys.INDENT, "yes")
setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "1")
setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no")
setOutputProperty(OutputKeys.ENCODING, "UTF-8")
}
Files.newBufferedWriter(cpFile.toPath()).use { w -> tf.transform(DOMSource(doc), StreamResult(w)) }
}
}
tasks.named("eclipse").configure { finalizedBy(injectIdeLibs) }
val eclipseModel = extensions.getByType<EclipseModel>()
fun Project.addResolvableEclipseConfigs() {
val jarAttr =
objects.named(org.gradle.api.attributes.LibraryElements::class, org.gradle.api.attributes.LibraryElements.JAR)
val apiAttr = objects.named(org.gradle.api.attributes.Usage::class, org.gradle.api.attributes.Usage.JAVA_API)
val compileOnlyRes =
configurations.create("eclipseCompileOnly") {
extendsFrom(configurations.getByName("compileOnly"))
isCanBeResolved = true
isCanBeConsumed = false
attributes.attribute(org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE, apiAttr)
attributes.attribute(org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarAttr)
}
val compileOnlyApiRes =
configurations.create("eclipseCompileOnlyApi") {
extendsFrom(configurations.getByName("compileOnlyApi"))
isCanBeResolved = true
isCanBeConsumed = false
attributes.attribute(org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE, apiAttr)
attributes.attribute(org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, jarAttr)
}
eclipseModel.classpath.plusConfigurations.addAll(listOf(compileOnlyRes, compileOnlyApiRes))
}
addResolvableEclipseConfigs()
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Executable
+251
View File
@@ -0,0 +1,251 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+94
View File
@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
BIN
View File
Binary file not shown.
-5
View File
@@ -1,5 +0,0 @@
_This lib folder contains external libs that are not provided by their author with Maven._
**(All external libraries located in this folder have been approved by their author!)**
PAFSpigot (Simonsator#5834 | https://www.spigotmc.org/resources/authors/simonsator.67188/ )
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>
Submodule
+1
Submodule libs/MyWorlds added at 659627d65e.
Submodule libs/Scoreboard-OG added at 3c2e10c103.
+1
Submodule libs/Utilities-OG added at 8b5c86cc9c.
-390
View File
@@ -1,390 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ BuildBattle - Ultimate building competition minigame
~ Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
~
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>plugily.projects</groupId>
<artifactId>buildbattle</artifactId>
<version>4.5.2</version>
<name>BuildBattle</name>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.projectKey>Plugily-Projects_BuildBattle</sonar.projectKey>
<sonar.organization>plugily-projects</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
</properties>
<repositories>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>citizens-repo</id>
<url>http://repo.citizensnpcs.co/</url>
</repository>
<repository>
<id>papi-repo</id>
<url>http://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
<repository>
<id>plugily-repo</id>
<url>https://maven.plugily.xyz/</url>
</repository>
<repository>
<id>mojang-repo</id>
<url>https://libraries.minecraft.net/</url>
</repository>
<repository>
<id>bstats-repo</id>
<url>https://repo.codemc.org/repository/maven-public</url>
</repository>
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public/</url>
</repository>
<repository>
<id>simonsators-repo</id>
<url>http://simonsator.de/repo/</url>
</repository>
<repository>
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
<repository>
<id>alessiodp-repo</id>
<url>https://repo.alessiodp.com/releases/</url>
</repository>
</repositories>
<dependencies>
<!-- Paper API-->
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.17.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>me.tigerhix.lib</groupId>
<artifactId>scoreboard</artifactId>
<version>1.0.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>plugily.projects</groupId>
<artifactId>commons-box-database</artifactId>
<version>1.3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>plugily.projects</groupId>
<artifactId>commons-box-minecraft</artifactId>
<version>1.3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>plugily.projects</groupId>
<artifactId>commons-box-classic</artifactId>
<version>1.3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>plugily.projects.inventoryframework</groupId>
<artifactId>IF</artifactId>
<version>0.10.0</version>
<scope>compile</scope>
<classifier>legacy-jar-with-dependencies</classifier>
</dependency>
<dependency>
<groupId>net.citizensnpcs</groupId>
<artifactId>citizensapi</artifactId>
<version>2.0.26-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>ch.ethz.globis.phtree</groupId>
<artifactId>phtree</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.10.10</version>
<scope>provided</scope>
</dependency>
<dependency>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
<scope>compile</scope>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>authlib</artifactId>
<version>1.5.21</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alessiodp.parties</groupId>
<artifactId>parties-api</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
</exclusion>
<exclusion>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>javac</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>de.simonsator</groupId>
<artifactId>Party-and-Friends-MySQL-Edition-Spigot-API</artifactId>
<version>1.3.2</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>be.maximvdw</groupId>
<artifactId>MVdWPlaceholderAPI</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>de.simonsator</groupId>
<artifactId>Spigot-Party-API-For-RedisBungee</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>de.simonsator</groupId>
<artifactId>partyandfriends</artifactId>
<version>1.0.52</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/PAFSpigot.jar</systemPath>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jetbrains/annotations -->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>21.0.1</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.9.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<windowtitle>Build Battle API docs for v${project.version}</windowtitle>
<description>Minecraft building minigame.
Build the best you can to win the game, play solo or in teams! API documentation for hooking Build Battle with your plugin.
</description>
<destDir>minecraft/buildbattle</destDir>
<isOffline>false</isOffline>
</configuration>
<executions>
<execution>
<id>attach-javadoc</id>
<phase>deploy</phase>
<goals>
<goal>jar</goal>
<goal>javadoc</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>me.tigerhix.lib.scoreboard</pattern>
<shadedPattern>plugily.projects.buildbattle.utils.scoreboard</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.commons.io</pattern>
<shadedPattern>plugily.projects.buildbattle.utils.commons.io</shadedPattern>
</relocation>
<relocation>
<pattern>com.zaxxer.hikari</pattern>
<shadedPattern>plugily.projects.buildbattle.database.hikari</shadedPattern>
</relocation>
<relocation>
<pattern>plugily.projects.commonsbox</pattern>
<shadedPattern>plugily.projects.buildbattle.commonsbox</shadedPattern>
</relocation>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>plugily.projects.buildbattle.utils.bstats</shadedPattern>
</relocation>
<relocation>
<pattern>plugily.projects.inventoryframework</pattern>
<shadedPattern>plugily.projects.buildbattle.inventoryframework</shadedPattern>
</relocation>
</relocations>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- External beta versions discord deployer plugin -->
<plugin>
<groupId>plugily.projects</groupId>
<artifactId>betty-maven-plugin</artifactId>
<version>1.0.2</version>
<configuration>
<changelogFile>${project.basedir}/CHANGELOG.md</changelogFile>
</configuration>
</plugin>
<!-- External beta versions discord deployer plugin -->
</plugins>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ftp</artifactId>
<version>3.4.3</version>
</extension>
</extensions>
</build>
<distributionManagement>
<repository>
<id>plugily-projects-repo</id>
<url>ftp://81.19.211.8</url>
</repository>
<site>
<id>plugily-projects-java-docs</id>
<name>thebridge</name>
<url>ftp://81.19.211.8</url>
</site>
</distributionManagement>
</project>
+15
View File
@@ -0,0 +1,15 @@
rootProject.name = "BuildBattle-OG"
// Fetch submodule content before the libraries below are wired in as subprojects.
ProcessBuilder("sh", "bootstrap.sh").directory(rootDir).inheritIO().start().let {
if (it.waitFor() != 0) throw GradleException("bootstrap.sh failed")
}
// Every git submodule under libs/ with a Gradle build becomes :libs:<name>, like Template-OG.
file("libs")
.listFiles()
?.filter { it.isDirectory && !it.name.startsWith(".") && file("${it.path}/build.gradle.kts").exists() }
?.forEach { dir ->
include(":libs:${dir.name}")
project(":libs:${dir.name}").projectDir = dir
}
@@ -1,219 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle;
import org.bukkit.Material;
import plugily.projects.commonsbox.minecraft.compat.xseries.XMaterial;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.utils.Debugger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* Created by Tom on 17/08/2015.
*/
public class ConfigPreferences {
private final Main plugin;
private final Map<String, List<String>> gameThemes = new HashMap<>();
private final List<String> endGameCommands = new ArrayList<>(), whitelistedCommands = new ArrayList<>();
private final List<Material> itemBlacklist = new ArrayList<>(), floorBlacklist = new ArrayList<>();
private final Map<Option, Boolean> options = new EnumMap<>(Option.class);
public ConfigPreferences(Main plugin) {
this.plugin = plugin;
loadOptions();
}
/**
* Clears all options and loads them again
*/
public void loadOptions() {
options.clear();
gameThemes.clear();
endGameCommands.clear();
whitelistedCommands.clear();
for(Option option : Option.values()) {
options.put(option, plugin.getConfig().getBoolean(option.getPath(), option.getDefault()));
}
endGameCommands.addAll(plugin.getConfig().getStringList("End-Game-Commands"));
whitelistedCommands.addAll(plugin.getConfig().getStringList("Whitelisted-Commands"));
loadThemes();
loadBlackList();
}
private void loadThemes() {
gameThemes.put(BaseArena.ArenaType.SOLO.getPrefix(), plugin.getConfig().getStringList("Themes.Classic"));
gameThemes.put(BaseArena.ArenaType.TEAM.getPrefix(), plugin.getConfig().getStringList("Themes.Teams"));
gameThemes.put(BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix() + "_EASY", plugin.getConfig().getStringList("Themes.Guess-The-Build.Easy"));
gameThemes.put(BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix() + "_MEDIUM", plugin.getConfig().getStringList("Themes.Guess-The-Build.Medium"));
gameThemes.put(BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix() + "_HARD", plugin.getConfig().getStringList("Themes.Guess-The-Build.Hard"));
Debugger.debug("Themes loaded: " + gameThemes);
}
public Map<String, List<String>> getGameThemes() {
return gameThemes;
}
public List<String> getThemes(String accessor) {
return Collections.unmodifiableList(gameThemes.getOrDefault(accessor, new ArrayList<>()));
}
public boolean isThemeBlacklisted(String theme) {
for(String s : plugin.getConfig().getStringList("Blacklisted-Themes")) {
if(s.equalsIgnoreCase(theme)) {
return true;
}
}
return false;
}
public List<String> getWinCommands(Position pos) {
return plugin.getConfig().getStringList("Win-Commands." + pos.getName());
}
public List<String> getEndGameCommands() {
return Collections.unmodifiableList(endGameCommands);
}
public List<Material> getItemBlacklist() {
return Collections.unmodifiableList(itemBlacklist);
}
public List<Material> getFloorBlacklist() {
return Collections.unmodifiableList(floorBlacklist);
}
private void loadBlackList() {
for(String item : plugin.getConfig().getStringList("Blacklisted-Item-Names")) {
Optional<XMaterial> opt = XMaterial.matchXMaterial(item.toUpperCase());
if(!opt.isPresent()) {
Debugger.sendConsoleMsg("&c[Build Battle] Invalid black listed item! " + item + " doesn't exist, are you sure it's properly named?");
continue;
}
itemBlacklist.add(opt.get().parseMaterial());
}
for(String item : plugin.getConfig().getStringList("Blacklisted-Floor-Materials")) {
Optional<XMaterial> opt = XMaterial.matchXMaterial(item.toUpperCase());
if(!opt.isPresent()) {
Debugger.sendConsoleMsg("&c[Build Battle] Invalid black listed item! " + item + " doesn't exist, are you sure it's properly named?");
continue;
}
floorBlacklist.add(opt.get().parseMaterial());
}
}
public List<String> getWhitelistedCommands() {
return Collections.unmodifiableList(whitelistedCommands);
}
public int getTimer(TimerType type, BaseArena arena) {
String prefix = "Time-Manager." + arena.getArenaType().getPrefix() + ".";
switch(type) {
case BUILD:
return plugin.getConfig().getInt(prefix + "Build-Time", 200);
case LOBBY:
return plugin.getConfig().getInt(prefix + "Lobby-Starting-Time", 60);
case PLOT_VOTE:
return plugin.getConfig().getInt(prefix + "Voting-Time-In-Seconds", 20);
case THEME_VOTE:
return plugin.getConfig().getInt(prefix + "Theme-Voting-Time-In-Seconds", 25);
case DELAYED_TASK:
return plugin.getConfig().getInt(prefix + "Delay-Between-Rounds-In-Seconds", 5);
case TIME_SHORTENER:
return plugin.getConfig().getInt(prefix + "Time-Shortener-In-Seconds", 10);
case THEME_SELECTION:
return plugin.getConfig().getInt(prefix + "Theme-Selection-Time-In-Seconds", 15);
case ALL_GUESSED:
return plugin.getConfig().getInt(prefix + "All-Guessed-In-Seconds", 5);
default:
return 0;
}
}
/**
* Returns whether option value is true or false
*
* @param option option to get value from
* @return true or false based on user plugin.getConfig()uration
*/
public boolean getOption(Option option) {
return options.get(option);
}
public enum TimerType {
BUILD, LOBBY, PLOT_VOTE, THEME_VOTE, DELAYED_TASK, TIME_SHORTENER, THEME_SELECTION, ALL_GUESSED
}
public enum Option {
BOSSBAR_ENABLED("Boss-Bar-Enabled", true), BUNGEE_ENABLED("BungeeActivated", false), DATABASE_ENABLED("DatabaseActivated", false),
INVENTORY_MANAGER_ENABLED("InventoryManager", true), BLOCK_COMMANDS_IN_GAME("Block-Commands-In-Game", true), REWARDS("Rewards-Enabled", false),
HEADS_COMMAND("Command-Instead-Of-Head-Menu.Enabled", false), ENABLE_SHORT_COMMANDS("Enable-Short-Commands", false),
DISABLE_SEPARATE_CHAT("Disable-Separate-Chat", false), DISABLE_PARTIES("Disable-Parties", true), ANNOUNCE_PLOTOWNER_LATER("Announce-PlotOwner-Later", false),
RUN_COMMAND_ON_REPORT("Run-Command-On-Report.Enabled", false), DISABLE_SPECTATORS("Disable-Spectators", false);
private final String path;
private final boolean def;
Option(String path, boolean def) {
this.path = path;
this.def = def;
}
public String getPath() {
return path;
}
/**
* @return default value of option if absent in plugin.getConfig()
*/
public boolean getDefault() {
return def;
}
}
public enum Position {
FIRST("First"), SECOND("Second"), THIRD("Third");
private final String name;
Position(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,314 +20,629 @@
package plugily.projects.buildbattle;
import me.tigerhix.lib.scoreboard.ScoreboardLib;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Filter;
import java.util.logging.LogRecord;
import nl.skbotnl.chatog.api.ChatOGAPI;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import plugily.projects.buildbattle.api.StatsStorage;
import org.bukkit.generator.ChunkGenerator;
import org.jetbrains.annotations.TestOnly;
import plugily.projects.buildbattle.arena.ArenaEvents;
import plugily.projects.buildbattle.arena.ArenaManager;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.managers.plots.PlotBorderManager;
import plugily.projects.buildbattle.arena.managers.plots.PlotMenuHandler;
import plugily.projects.buildbattle.arena.vote.VoteEvents;
import plugily.projects.buildbattle.arena.vote.VoteItems;
import plugily.projects.buildbattle.boot.AdditionalValueInitializer;
import plugily.projects.buildbattle.boot.MessageInitializer;
import plugily.projects.buildbattle.boot.PlaceholderInitializer;
import plugily.projects.buildbattle.boot.TrueOGPlaceholderInitializer;
import plugily.projects.buildbattle.chat.BuildBattleChatFormatter;
import plugily.projects.buildbattle.commands.ForceStartCommand;
import plugily.projects.buildbattle.commands.HubCommand;
import plugily.projects.buildbattle.commands.HubCommandListener;
import plugily.projects.buildbattle.commands.JoinLobbyCommand;
import plugily.projects.buildbattle.commands.VoteCommandListener;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.events.ChatEvents;
import plugily.projects.buildbattle.events.GameEvents;
import plugily.projects.buildbattle.events.JoinEvents;
import plugily.projects.buildbattle.events.LobbyEvents;
import plugily.projects.buildbattle.events.QuitEvents;
import plugily.projects.buildbattle.events.spectator.SpectatorEvents;
import plugily.projects.buildbattle.events.spectator.SpectatorItemEvents;
import plugily.projects.buildbattle.handlers.BungeeManager;
import plugily.projects.buildbattle.handlers.ChatManager;
import plugily.projects.buildbattle.handlers.HolidayManager;
import plugily.projects.buildbattle.handlers.PermissionManager;
import plugily.projects.buildbattle.handlers.PlaceholderManager;
import plugily.projects.buildbattle.handlers.items.SpecialItemsManager;
import plugily.projects.buildbattle.handlers.language.LanguageManager;
import plugily.projects.buildbattle.handlers.party.PartyHandler;
import plugily.projects.buildbattle.handlers.party.PartySupportInitializer;
import plugily.projects.buildbattle.handlers.reward.RewardsFactory;
import plugily.projects.buildbattle.handlers.setup.SetupInventoryEvents;
import plugily.projects.buildbattle.handlers.sign.SignManager;
import plugily.projects.buildbattle.menus.options.OptionsMenuHandler;
import plugily.projects.buildbattle.menus.options.OptionsRegistry;
import plugily.projects.buildbattle.menus.options.registry.banner.BannerMenu;
import plugily.projects.buildbattle.menus.themevoter.VoteMenuListener;
import plugily.projects.buildbattle.user.User;
import plugily.projects.buildbattle.user.UserManager;
import plugily.projects.buildbattle.user.data.MysqlManager;
import plugily.projects.buildbattle.utils.CuboidSelector;
import plugily.projects.buildbattle.utils.Debugger;
import plugily.projects.buildbattle.utils.ExceptionLogHandler;
import plugily.projects.buildbattle.utils.LegacyDataFixer;
import plugily.projects.buildbattle.utils.MessageUtils;
import plugily.projects.buildbattle.utils.UpdateChecker;
import plugily.projects.buildbattle.utils.services.ServiceRegistry;
import plugily.projects.commonsbox.database.MysqlDatabase;
import plugily.projects.commonsbox.minecraft.compat.ServerVersion;
import plugily.projects.commonsbox.minecraft.compat.events.EventsInitializer;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.commonsbox.minecraft.misc.MiscUtils;
import plugily.projects.commonsbox.minecraft.serialization.InventorySerializer;
import java.util.Arrays;
import plugily.projects.buildbattle.handlers.LanguageMigrator;
import plugily.projects.buildbattle.handlers.language.TrueOGLanguageManager;
import plugily.projects.buildbattle.handlers.menu.OptionsRegistry;
import plugily.projects.buildbattle.handlers.misc.ArenaWorldProvisioner;
import plugily.projects.buildbattle.handlers.misc.BlacklistManager;
import plugily.projects.buildbattle.handlers.misc.BuilderCreativeManager;
import plugily.projects.buildbattle.handlers.misc.GameModeInventoriesGuard;
import plugily.projects.buildbattle.handlers.misc.HeadDatabaseManager;
import plugily.projects.buildbattle.handlers.misc.MyWorldsManager;
import plugily.projects.buildbattle.handlers.misc.PreJoinLocationListener;
import plugily.projects.buildbattle.handlers.misc.PreJoinLocationStore;
import plugily.projects.buildbattle.handlers.misc.ReconnectToMainWorldListener;
import plugily.projects.buildbattle.handlers.misc.ScoreboardOGBridge;
import plugily.projects.buildbattle.handlers.misc.VoidChunkGenerator;
import plugily.projects.buildbattle.handlers.setup.SetupCategoryManager;
import plugily.projects.buildbattle.handlers.stats.BuildBattleScores;
import plugily.projects.buildbattle.handlers.themes.ThemeManager;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.api.handlers.language.ILanguageManager;
import plugily.projects.minigamesbox.classic.PluginMain;
import plugily.projects.minigamesbox.classic.handlers.setup.SetupInventory;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.PluginSetupCategoryManager;
/**
* Created by Tom on 17/08/2015.
* Created by Tom on 17/08/2015. Updated by Tigerpanzer_02 on 03.12.2021
*/
//todo setup handler recode
//todo arenas handler recode
//todo inventoryframework
public class Main extends JavaPlugin {
public class Main extends PluginMain {
private ArgumentsRegistry registry;
private ExceptionLogHandler exceptionLogHandler;
private ChatManager chatManager;
private ConfigPreferences configPreferences;
private MysqlDatabase database;
private UserManager userManager;
private BungeeManager bungeeManager;
private SignManager signManager;
private CuboidSelector cuboidSelector;
private VoteItems voteItems;
private OptionsRegistry optionsRegistry;
private SpecialItemsManager specialItemsManager;
private boolean forceDisable = false;
private PartyHandler partyHandler;
private RewardsFactory rewardsHandler;
private PlotMenuHandler plotMenuHandler;
private VoteItems voteItems;
private HeadDatabaseManager headDatabaseManager;
private ThemeManager themeManager;
private BlacklistManager blacklistManager;
private OptionsRegistry optionsRegistry;
private ArenaRegistry arenaRegistry;
private ArenaManager arenaManager;
private ArgumentsRegistry argumentsRegistry;
private PlotMenuHandler plotMenuHandler;
private MyWorldsManager myWorldsManager;
private ArenaWorldProvisioner arenaWorldProvisioner;
private PreJoinLocationStore preJoinLocationStore;
private BuilderCreativeManager builderCreativeManager;
private PlotBorderManager plotBorderManager;
private GameModeInventoriesGuard gmiGuard;
private ILanguageManager languageManager;
private BuildBattleScores buildBattleScores;
public CuboidSelector getCuboidSelector() {
return cuboidSelector;
}
@TestOnly
public Main() {
public VoteItems getVoteItems() {
return voteItems;
}
super();
public OptionsRegistry getOptionsRegistry() {
return optionsRegistry;
}
public BungeeManager getBungeeManager() {
return bungeeManager;
}
public SignManager getSignManager() {
return signManager;
}
public ConfigPreferences getConfigPreferences() {
return configPreferences;
}
public SpecialItemsManager getSpecialItemsManager() {
return specialItemsManager;
}
public ArgumentsRegistry getArgumentsRegistry() {
return registry;
}
@Override
public void onEnable() {
if(!validateIfPluginShouldStart()) {
return;
}
ServiceRegistry.registerService(this);
exceptionLogHandler = new ExceptionLogHandler(this);
Debugger.setEnabled(getDescription().getVersion().contains("debug") || getConfig().getBoolean("Debug"));
Debugger.debug("Main setup started");
saveDefaultConfig();
for(String s : Arrays.asList("arenas", "particles", "special_items", "stats", "voteItems", "mysql", "biomes", "bungee", "rewards")) {
ConfigUtils.getConfig(this, s);
}
LanguageManager.init(this);
chatManager = new ChatManager(this);
configPreferences = new ConfigPreferences(this);
new LegacyDataFixer(this);
initializeClasses();
}
@Override
public void onEnable() {
private void checkUpdate() {
if(!getConfig().getBoolean("Update-Notifier.Enabled", true)) {
return;
}
UpdateChecker.init(this, 44703).requestUpdateCheck().whenComplete((result, exception) -> {
if(!result.requiresUpdate()) {
return;
}
if(result.getNewestVersion().contains("b")) {
if(getConfig().getBoolean("Update-Notifier.Notify-Beta-Versions", true)) {
Debugger.sendConsoleMsg("&c[Build Battle] Your software is ready for update! However it's a BETA VERSION. Proceed with caution.");
Debugger.sendConsoleMsg("&c[Build Battle] Current version %old%, latest version %new%".replace("%old%", getDescription().getVersion()).replace("%new%",
result.getNewestVersion()));
}
return;
}
MessageUtils.updateIsHere();
Debugger.sendConsoleMsg("&aYour Build Battle plugin is outdated! Download it to keep with latest changes and fixes.");
Debugger.sendConsoleMsg("&aDisable this option in config.yml if you wish.");
Debugger.sendConsoleMsg("&eCurrent version: &c" + getDescription().getVersion() + " &eLatest version: &a" + result.getNewestVersion());
});
}
long start = System.currentTimeMillis();
installDebugNoiseFilter();
// Write bundled powerups.yml to the data folder so the shaded
// MiniGamesBox-Classic reader finds it instead of logging
// "File powerups.yml does not exist!".
if (!new java.io.File(getDataFolder(), "powerups.yml").exists()) {
private boolean validateIfPluginShouldStart() {
try {
Class.forName("org.spigotmc.SpigotConfig");
} catch(Exception e) {
MessageUtils.thisVersionIsNotSupported();
Debugger.sendConsoleMsg("&cYour server software is not supported by Build Battle!");
Debugger.sendConsoleMsg("&cWe support only Spigot and Spigot forks only! Shutting off...");
forceDisable = true;
getServer().getPluginManager().disablePlugin(this);
return false;
}
if(ServerVersion.Version.isCurrentLower(ServerVersion.Version.v1_8_R1)) {
MessageUtils.thisVersionIsNotSupported();
Debugger.sendConsoleMsg("&cYour server version is not supported by Build Battle!");
Debugger.sendConsoleMsg("&cSadly, we must shut off. Maybe you consider updating your server version?");
forceDisable = true;
getServer().getPluginManager().disablePlugin(this);
return false;
}
return true;
}
saveResource("powerups.yml", false);
//order matters
private void initializeClasses() {
ScoreboardLib.setPluginInstance(this);
if(getConfig().getBoolean("BungeeActivated")) {
bungeeManager = new BungeeManager(this);
}
if(configPreferences.getOption(ConfigPreferences.Option.DATABASE_ENABLED)) {
FileConfiguration config = ConfigUtils.getConfig(this, "mysql");
database = new MysqlDatabase(config.getString("user"), config.getString("password"), config.getString("address"), config.getLong("maxLifeTime", 1800000));
}
registry = new ArgumentsRegistry(this);
userManager = new UserManager(this);
PermissionManager.init();
new SetupInventoryEvents(this);
signManager = new SignManager(this);
ArenaRegistry.registerArenas();
signManager.loadSigns();
signManager.updateSigns();
specialItemsManager = new SpecialItemsManager(this);
voteItems = new VoteItems();
new VoteEvents(this);
new LobbyEvents(this);
new ChatEvents(this);
optionsRegistry = new OptionsRegistry(this);
new OptionsMenuHandler(this);
Metrics metrics = new Metrics(this, 2491);
metrics.addCustomChart(new org.bstats.charts.SimplePie("bungeecord_hooked", () -> String.valueOf(configPreferences.getOption(ConfigPreferences.Option.BUNGEE_ENABLED))));
metrics.addCustomChart(new org.bstats.charts.SimplePie("locale_used", LanguageManager.getPluginLocale()::getPrefix));
metrics.addCustomChart(new org.bstats.charts.SimplePie("update_notifier", () -> {
if(getConfig().getBoolean("Update-Notifier.Enabled", true)) {
return getConfig().getBoolean("Update-Notifier.Notify-Beta-Versions", true) ? "Enabled with beta notifier" : "Enabled";
}
return getConfig().getBoolean("Update-Notifier.Notify-Beta-Versions", true) ? "Beta notifier only" : "Disabled";
}));
new JoinEvents(this);
new QuitEvents(this);
if(getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
new PlaceholderManager().register();
}
cuboidSelector = new CuboidSelector(this);
UpdateChecker.init(this, 44703);
checkUpdate();
new GameEvents(this);
new VoteMenuListener(this);
new HolidayManager(this);
new SpectatorEvents(this);
new SpectatorItemEvents(this);
BannerMenu.init(this);
partyHandler = new PartySupportInitializer().initialize(this);
rewardsHandler = new RewardsFactory(this);
plotMenuHandler = new PlotMenuHandler(this);
new EventsInitializer().initialize(this);
MiscUtils.sendStartUpMessage(this, "BuildBattle", getDescription(), true, true);
}
@Override
public void onDisable() {
if(forceDisable) return;
Debugger.debug("System disabling...");
Bukkit.getLogger().removeHandler(exceptionLogHandler);
for(BaseArena arena : ArenaRegistry.getArenas()) {
for(Player player : arena.getPlayers()) {
arena.getScoreboardManager().stopAllScoreboards();
arena.doBarAction(BaseArena.BarAction.REMOVE, player);
arena.teleportToEndLocation(player);
player.setGameMode(GameMode.SURVIVAL);
player.getInventory().clear();
player.getInventory().setArmorContents(null);
player.getActivePotionEffects().forEach(pe -> player.removePotionEffect(pe.getType()));
if(configPreferences.getOption(ConfigPreferences.Option.INVENTORY_MANAGER_ENABLED)) {
InventorySerializer.loadInventory(this, player);
}
}
arena.getPlotManager().getPlots().forEach(Plot::fullyResetPlot);
}
for(Player player : getServer().getOnlinePlayers()) {
User user = userManager.getUser(player);
if(userManager.getDatabase() instanceof MysqlManager) {
StringBuilder update = new StringBuilder(" SET ");
for(StatsStorage.StatisticType stat : StatsStorage.StatisticType.values()) {
if(!stat.isPersistent()) continue;
int userStat = user.getStat(stat);
if(update.toString().equalsIgnoreCase(" SET ")) {
update.append(stat.getName()).append('=').append(userStat);
}
update.append(", ").append(stat.getName()).append('=').append(userStat);
}
MysqlManager db = (MysqlManager) userManager.getDatabase();
//copy of userManager#saveStatistic but without async database call that's not allowed in onDisable method.
db.getDatabase().executeUpdate("UPDATE " + db.getTableName()
+ update.toString() + " WHERE UUID='" + user.getUniqueId().toString() + "';");
continue;
}
for(StatsStorage.StatisticType stat : StatsStorage.StatisticType.values()) {
userManager.getDatabase().saveStatistic(user, stat);
}
new LanguageMigrator(this);
MessageInitializer messageInitializer = new MessageInitializer(this);
// Must precede super.onEnable(): SignManager caches Signs.Lines and the
// game-state names into
// final fields while the base plugin enables, and never re-reads them (not even
// on /bba reload).
installTrueOGColorizer();
super.onEnable();
getDebugger().debug("[System] [Plugin] Initialization start");
arenaRegistry = new ArenaRegistry(this);
myWorldsManager = new MyWorldsManager(this);
if (!myWorldsManager.initialize()) {
// super.onEnable() already ran, so a bare return would leave the plugin marked
// enabled with no arenas, commands or listeners registered. Fail fast instead.
// Note this runs onDisable() re-entrantly, inside onEnable(). That is safe
// today only
// because registerArenas() has not run yet, so onDisable()'s loop over the
// arena
// registry is empty and never dereferences the still-null arenaManager. If
// arenas ever
// become populated earlier, move this check above super.onEnable() instead.
getServer().getPluginManager().disablePlugin(this);
return;
}
preJoinLocationStore = new PreJoinLocationStore(this);
new PlaceholderInitializer(this);
messageInitializer.registerMessages();
new AdditionalValueInitializer(this);
initializePluginClasses();
// After AdditionalValueInitializer, which registers the POINTS_TOTAL statistic
// this reads.
buildBattleScores = new BuildBattleScores(this);
if (getServer().getPluginManager().getPlugin("Utilities-OG") != null) {
new TrueOGPlaceholderInitializer(buildBattleScores);
}
getDebugger().debug("Full {0} plugin enabled", getName());
getDebugger().debug("[System] [Plugin] Initialization finished took {0}ms", System.currentTimeMillis() - start);
}
if(configPreferences.getOption(ConfigPreferences.Option.DATABASE_ENABLED)) {
getMysqlDatabase().shutdownConnPool();
// Route language values through TrueOG's colorizer when Utilities-OG is
// installed. It is a
// compileOnly dependency, so only build the decorator once its classes are
// known present.
// Every plugin is loaded before any is enabled, so this check is already valid
// pre-onEnable.
private void installTrueOGColorizer() {
if (getServer().getPluginManager().getPlugin("Utilities-OG") == null) {
getLogger().info("Utilities-OG is not installed, so messages keep their default formatting.");
return;
}
// Delegate resolved lazily: PluginMain has not built its LanguageManager yet at
// this point.
languageManager = new TrueOGLanguageManager(super::getLanguageManager);
}
}
public ChatManager getChatManager() {
return chatManager;
}
/**
* {@inheritDoc}
*
* <p>
* Returns the colorizing decorator once {@link #installTrueOGColorizer()} has
* run, which is before {@code super.onEnable()} so that values the base plugin
* caches at startup (join sign lines, game-state names) are already colorized.
*/
@Override
public ILanguageManager getLanguageManager() {
public MysqlDatabase getMysqlDatabase() {
return database;
}
return languageManager != null ? languageManager : super.getLanguageManager();
public UserManager getUserManager() {
return userManager;
}
}
public PartyHandler getPartyHandler() {
return partyHandler;
}
// Suppress known non-actionable startup noise from shaded MiniGamesBox-Classic.
private void installDebugNoiseFilter() {
public RewardsFactory getRewardsHandler() {
return rewardsHandler;
}
java.util.logging.Logger jul = java.util.logging.Logger.getLogger(getName());
Filter previous = jul.getFilter();
jul.setFilter(new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
String msg = record.getMessage();
// Raw locale records contain color codes and concatenated values,
// so match them by substring rather than prefix.
if (msg != null && msg.contains("Loaded locale"))
return false;
return previous == null || previous.isLoggable(record);
}
});
}
public void initializePluginClasses() {
addFileName("themes");
addFileName("vote_items");
blacklistManager = new BlacklistManager(this);
headDatabaseManager = new HeadDatabaseManager(this);
themeManager = new ThemeManager(this);
BaseArena.init(this);
new ArenaEvents(this);
arenaManager = new ArenaManager(this);
gmiGuard = new GameModeInventoriesGuard(this, player -> isArenaWorld(player.getWorld()));
builderCreativeManager = new BuilderCreativeManager(this);
plotBorderManager = new PlotBorderManager(this);
// Load worlds first, or MiniGamesBox generates vanilla ones on register.
arenaWorldProvisioner = new ArenaWorldProvisioner(this);
arenaWorldProvisioner.provisionArenaWorlds();
arenaRegistry.registerArenas();
// /reload leaves players standing in arena worlds with no suspension.
gmiGuard.sweepOnlinePlayers();
new ReconnectToMainWorldListener(this);
new PreJoinLocationListener(this);
PluginCommand hubCommand = getCommand("hub");
HubCommand hub = new HubCommand(this);
if (hubCommand != null) {
hubCommand.setExecutor(hub);
} else {
getLogger().warning("The 'hub' command is missing from plugin.yml, so /hub will not work.");
}
registerCommand("bbjoin", new JoinLobbyCommand(this));
registerCommand("bbforcestart", new ForceStartCommand(this));
// Claims /v and /vote inside BuildBattle worlds before VotingPlugin sees them.
new VoteCommandListener(this);
// Claims /hub, /lobby and /spawn inside BuildBattle worlds the same way, so
// another minigame's /hub or Spawn-OG's /spawn never handles an arena player.
new HubCommandListener(this, hub);
ensureCommandWhitelist();
registerChatFormatter();
myWorldsManager.synchronizeArenaWorldInventories();
getSignManager().loadSigns();
getSignManager().updateSigns();
argumentsRegistry = new ArgumentsRegistry(this);
voteItems = new VoteItems(this);
new VoteEvents(this);
plotMenuHandler = new PlotMenuHandler(this);
optionsRegistry = new OptionsRegistry(this);
optionsRegistry.registerOptions();
}
public VoteItems getVoteItems() {
return voteItems;
}
public HeadDatabaseManager getHeadDatabaseManager() {
return headDatabaseManager;
}
public ThemeManager getThemeManager() {
return themeManager;
}
public BlacklistManager getBlacklistManager() {
return blacklistManager;
}
public OptionsRegistry getOptionsRegistry() {
return optionsRegistry;
}
public PlotMenuHandler getPlotMenuHandler() {
return plotMenuHandler;
}
public BuildBattleScores getBuildBattleScores() {
return buildBattleScores;
}
public ArenaWorldProvisioner getArenaWorldProvisioner() {
return arenaWorldProvisioner;
}
// Backs the BuildBattle-OG:void id pinned onto arena worlds in MyWorlds.
@Override
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
return new VoidChunkGenerator();
}
public MyWorldsManager getMyWorldsManager() {
return myWorldsManager;
}
public BuilderCreativeManager getBuilderCreativeManager() {
return builderCreativeManager;
}
public PlotBorderManager getPlotBorderManager() {
return plotBorderManager;
}
public GameModeInventoriesGuard getGmiGuard() {
return gmiGuard;
}
// BuildBattle territory: every registered arena's lobby and game worlds plus
// the plot worlds arenas.yml names, which MiniGamesBox does not list.
public boolean isArenaWorld(World world) {
if (world == null) {
return false;
}
if (arenaRegistry != null) {
for (World arenaWorld : arenaRegistry.getArenaWorlds()) {
if (arenaWorld != null && arenaWorld.getName().equals(world.getName())) {
return true;
}
}
for (World arenaWorld : arenaRegistry.getArenaIngameWorlds()) {
if (arenaWorld != null && arenaWorld.getName().equals(world.getName())) {
return true;
}
}
}
return myWorldsManager != null && myWorldsManager.isConfiguredArenaWorld(world.getName());
}
// Chat-OG routes a world to a game by the letter prefix of its name (BB1-hub
// and
// BB1-map both belong to key "BB"), so the formatter is registered once per
// distinct prefix across the configured arena worlds.
private void registerChatFormatter() {
if (getServer().getPluginManager().getPlugin("Chat-OG") == null) {
getLogger().info("Chat-OG is not installed, so BuildBattle chat keeps its default formatting.");
return;
}
Set<String> keys = new LinkedHashSet<>();
for (IPluginArena arena : getArenaRegistry().getArenas()) {
addGameKey(keys, arena.getLobbyLocation());
addGameKey(keys, arena.getStartLocation());
}
if (keys.isEmpty()) {
getLogger().warning("No arena world follows the <prefix><number>-<name> convention, so no BuildBattle "
+ "chat formatter was registered.");
return;
}
BuildBattleChatFormatter formatter = new BuildBattleChatFormatter(this);
for (String key : keys) {
if (!ChatOGAPI.setFormatter(key, formatter)) {
getLogger().warning("Chat-OG was not ready, so no chat formatter was registered for " + key + ".");
}
}
}
// Mirrors Chat-OG's own parse: letters, then digits, then '-'. Anything else is
// not part of a multi world game and contributes no key.
private static void addGameKey(Set<String> keys, Location location) {
if (location == null || location.getWorld() == null) {
return;
}
String worldName = location.getWorld().getName();
int index = 0;
while (index < worldName.length() && Character.isLetter(worldName.charAt(index))) {
index++;
}
if (index == 0) {
return;
}
int digitStart = index;
while (index < worldName.length() && Character.isDigit(worldName.charAt(index))) {
index++;
}
if (index == digitStart || index >= worldName.length() || worldName.charAt(index) != '-') {
return;
}
keys.add(worldName.substring(0, digitStart));
}
// MiniGamesBox blocks every command an arena member runs that is not on
// Commands.Whitelist, and it does not check whether the event was already
// cancelled, so the commands HubCommandListener claims have to be listed or
// the player gets a "blocked" message after being sent home. Older configs
// predate /lobby and /spawn, so the list is topped up here.
private void ensureCommandWhitelist() {
final java.util.List<String> whitelist = new java.util.ArrayList<>(
getConfig().getStringList("Commands.Whitelist"));
boolean changed = false;
for (String required : new String[] { "hub", "lobby", "spawn", "bbjoin", "bbforcestart" }) {
if (whitelist.stream().noneMatch(required::equalsIgnoreCase)) {
whitelist.add(required);
changed = true;
}
}
if (changed) {
getConfig().set("Commands.Whitelist", whitelist);
saveConfig();
}
}
private void registerCommand(String name, CommandExecutor executor) {
PluginCommand command = getCommand(name);
if (command == null) {
getLogger()
.warning("The '" + name + "' command is missing from plugin.yml, so /" + name + " will not work.");
return;
}
command.setExecutor(executor);
if (executor instanceof TabCompleter tabCompleter) {
command.setTabCompleter(tabCompleter);
}
}
public void savePreJoinLocation(Player player) {
savePreJoinLocation(player.getUniqueId(), player.getLocation());
}
public void savePreJoinLocation(UUID playerId, Location location) {
if (preJoinLocationStore != null && location != null && location.getWorld() != null) {
preJoinLocationStore.put(playerId, location);
}
}
public boolean hasPreJoinLocation(UUID playerId) {
return preJoinLocationStore != null && preJoinLocationStore.getWorldName(playerId) != null;
}
public void removePreJoinLocation(UUID playerId) {
if (preJoinLocationStore != null) {
preJoinLocationStore.remove(playerId);
}
}
public Location getAndRemovePreJoinLocation(UUID playerId) {
if (preJoinLocationStore == null) {
return null;
}
// Pulls the stored world back in through MyWorlds when it is unloaded.
Location location = preJoinLocationStore.getOrLoadWorld(playerId);
preJoinLocationStore.remove(playerId);
return location;
}
@Override
public void onDisable() {
// Order matters on /reload, where players stay online. super.onDisable() stops
// every arena, which restores inventories through MiniGamesBox; lifting the
// GameModeInventories suspension before that lets GMI swap mid-restore and file
// arena state as the player's real survival inventory. The location store is
// flushed last so anything teardown changes still reaches disk.
super.onDisable();
// Arena stop already released every claimed sidebar; this catches a stray one.
ScoreboardOGBridge.releaseAll();
if (builderCreativeManager != null) {
builderCreativeManager.revokeAll();
}
if (plotBorderManager != null) {
plotBorderManager.clearAll();
}
if (gmiGuard != null) {
gmiGuard.releaseAll();
}
if (preJoinLocationStore != null) {
preJoinLocationStore.shutdown();
}
}
@Override
public ArenaRegistry getArenaRegistry() {
return arenaRegistry;
}
@Override
public ArenaManager getArenaManager() {
return arenaManager;
}
@Override
public ArgumentsRegistry getArgumentsRegistry() {
return argumentsRegistry;
}
@Override
public PluginSetupCategoryManager getSetupCategoryManager(SetupInventory setupInventory) {
return new SetupCategoryManager(setupInventory);
}
public PlotMenuHandler getPlotMenuHandler() {
return plotMenuHandler;
}
}
@@ -1,127 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.commonsbox.sorter.SortUtils;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.user.data.MysqlManager;
import plugily.projects.buildbattle.utils.Debugger;
import plugily.projects.buildbattle.utils.MessageUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
/**
* @author Plajer, TomTheDeveloper
* @since 2.0.0
* <p>
* Class for accessing users statistics.
*/
public class StatsStorage {
private static final Main plugin = JavaPlugin.getPlugin(Main.class);
/**
* Get all UUID's sorted ascending by Statistic Type
*
* @param stat Statistic type to get (kills, deaths etc.)
* @return Map of UUID keys and Integer values sorted in ascending order of requested statistic type
*/
public static Map<UUID, Integer> getStats(StatisticType stat) {
if(plugin.getConfigPreferences().getOption(ConfigPreferences.Option.DATABASE_ENABLED)) {
try(Connection connection = plugin.getMysqlDatabase().getConnection();
Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery("SELECT UUID, " + stat.getName() + " FROM " + ((MysqlManager) plugin.getUserManager().getDatabase()).getTableName() + " ORDER BY " + stat.getName())) {
Map<UUID, Integer> column = new LinkedHashMap<>();
while(set.next()) {
column.put(UUID.fromString(set.getString("UUID")), set.getInt(stat.getName()));
}
return column;
} catch(SQLException e) {
e.printStackTrace();
MessageUtils.errorOccurred();
Debugger.sendConsoleMsg("Cannot get contents from MySQL database!");
Debugger.sendConsoleMsg("Check configuration of mysql.yml file or disable mysql option in config.yml");
return Collections.emptyMap();
}
}
FileConfiguration config = ConfigUtils.getConfig(plugin, "stats");
Map<UUID, Integer> stats = new TreeMap<>();
for(String string : config.getKeys(false)) {
if("data-version".equals(string)) {
continue;
}
stats.put(UUID.fromString(string), config.getInt(string + "." + stat.getName()));
}
return SortUtils.sortByValue(stats);
}
/**
* Get user statistic based on StatisticType
*
* @param player Online player to get data from
* @param statisticType Statistic type to get (blocks placed, wins etc.)
* @return int of statistic
* @see StatisticType
*/
public static int getUserStats(Player player, StatisticType statisticType) {
return plugin.getUserManager().getUser(player).getStat(statisticType);
}
/**
* Available statistics to get.
*/
//todo separate stats for different arena modes!
public enum StatisticType {
BLOCKS_PLACED("blocksplaced", true), BLOCKS_BROKEN("blocksbroken", true), GAMES_PLAYED("gamesplayed", true), WINS("wins", true),
LOSES("loses", true), HIGHEST_WIN("highestwin", true), HIGHEST_POINTS("higestpoints", true), TOTAL_POINTS_EARNED("totalpointsearned", true), PARTICLES_USED("particles", true), SUPER_VOTES("supervotes", true),
LOCAL_POINTS("points", false), LOCAL_GUESS_THE_BUILD_POINTS("gtb_points", false), REPORTS("reports", false);
private final String name;
private final boolean persistent;
StatisticType(String name, boolean persistent) {
this.name = name;
this.persistent = persistent;
}
public String getName() {
return name;
}
public boolean isPersistent() {
return persistent;
}
}
}
@@ -1,48 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event;
import org.bukkit.event.Event;
import plugily.projects.buildbattle.arena.impl.BaseArena;
/**
* Represents BuildBattle game related events.
*/
public abstract class BBEvent extends Event {
protected BaseArena arena;
public BBEvent(BaseArena eventArena) {
arena = eventArena;
}
/**
* Returns event arena
* Returns null when called from BBPlayerStatisticChangeEvent when super votes are added via command
* To get more information about arena you can check instanceof SoloArena, TeamArena and GuessTheBuildArena
* and then cast it.
*
* @return event arena
*/
public BaseArena getArena() {
return arena;
}
}
@@ -1,59 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.game;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.impl.BaseArena;
/**
* Called when arena states changes
*/
public class BBGameChangeStateEvent extends BBEvent {
private static final HandlerList handlers = new HandlerList();
private final ArenaState gameState;
private final ArenaState previous;
public BBGameChangeStateEvent(ArenaState gameState, BaseArena arena, ArenaState previous) {
super(arena);
this.gameState = gameState;
this.previous = previous;
}
public static HandlerList getHandlerList() {
return handlers;
}
public ArenaState getState() {
return gameState;
}
public ArenaState getPreviousState() {
return previous;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
@@ -1,46 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.game;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
/**
* Called when game is ended
*/
public class BBGameEndEvent extends BBEvent {
private static final HandlerList handlers = new HandlerList();
public BBGameEndEvent(BaseArena arena) {
super(arena);
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
@@ -1,71 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.game;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
/**
* Called when player joins arena
*/
public class BBGameJoinEvent extends BBEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled;
private final Player player;
public BBGameJoinEvent(Player player, BaseArena arena) {
super(arena);
this.player = player;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
/**
* Get player associated with this event
*
* @return player
*/
public Player getPlayer() {
return player;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
@@ -1,58 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.game;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
/**
* Called when player leaves arena
*/
public class BBGameLeaveEvent extends BBEvent {
private static final HandlerList handlers = new HandlerList();
private final Player player;
public BBGameLeaveEvent(Player player, BaseArena arena) {
super(arena);
this.player = player;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
/**
* Get player associated with this event
*
* @return player
*/
public Player getPlayer() {
return player;
}
}
@@ -1,46 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.game;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
/**
* Called when game is started
*/
public class BBGameStartEvent extends BBEvent {
private static final HandlerList handlers = new HandlerList();
public BBGameStartEvent(BaseArena arena) {
super(arena);
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
@@ -0,0 +1,65 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.guess;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.arena.GuessArena;
import plugily.projects.buildbattle.handlers.themes.GuessTheme;
import plugily.projects.minigamesbox.api.events.PlugilyEvent;
/**
* @author Tigerpanzer_02
* @since 5.0.0
* <p>
* Called when player guess the theme right
*/
public class PlayerThemeGuessEvent extends PlugilyEvent {
private static final HandlerList HANDLERS = new HandlerList();
private final GuessTheme theme;
public PlayerThemeGuessEvent(GuessArena eventArena, GuessTheme theme) {
super(eventArena);
this.theme = theme;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
public GuessTheme getTheme() {
return theme;
}
}
@@ -1,72 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.player;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.Nullable;
import plugily.projects.buildbattle.api.StatsStorage;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
/**
* @author Plajer
* @see StatsStorage.StatisticType
* @since 3.4.1
* <p>
* Called when player receive new statistic.
*/
public class BBPlayerStatisticChangeEvent extends BBEvent {
private static final HandlerList HANDLERS = new HandlerList();
private final Player player;
private final StatsStorage.StatisticType statisticType;
private final int number;
public BBPlayerStatisticChangeEvent(@Nullable BaseArena eventArena, Player player, StatsStorage.StatisticType statisticType, int number) {
super(eventArena);
this.player = player;
this.statisticType = statisticType;
this.number = number;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
public Player getPlayer() {
return player;
}
public StatsStorage.StatisticType getStatisticType() {
return statisticType;
}
public int getNumber() {
return number;
}
}
@@ -1,25 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* All in-game player related events.
*/
package plugily.projects.buildbattle.api.event.player;
@@ -1,70 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.plot;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
public class BBPlayerChoosePlotEvent extends BBEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Player player;
private final Plot plot;
private boolean isCancelled;
public BBPlayerChoosePlotEvent(Player player, Plot plot, BaseArena arena) {
super(arena);
this.player = player;
this.plot = plot;
this.isCancelled = false;
}
public static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() {
return player;
}
public Plot getPlot() {
return plot;
}
@Override
public boolean isCancelled() {
return this.isCancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.isCancelled = cancelled;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
@@ -0,0 +1,85 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.api.event.plot;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.minigamesbox.api.events.PlugilyEvent;
public class PlotPlayerChooseEvent extends PlugilyEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Player player;
private final Plot plot;
private boolean isCancelled;
public PlotPlayerChooseEvent(Player player, Plot plot, BaseArena baseArena) {
super(baseArena);
this.player = player;
this.plot = plot;
this.isCancelled = false;
}
public static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() {
return player;
}
public Plot getPlot() {
return plot;
}
@Override
public boolean isCancelled() {
return this.isCancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.isCancelled = cancelled;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,36 +21,45 @@
package plugily.projects.buildbattle.api.event.plot;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.minigamesbox.api.events.PlugilyEvent;
/**
* @author Plajer
* @since 4.0.0-pre-12
* <p>
* Called when player receive plot in game after the game starts
* <p>
* Called when player receive plot in game after the game starts
*/
public class BBPlayerPlotReceiveEvent extends BBEvent {
public class PlotPlayerReceiveEvent extends PlugilyEvent {
private static final HandlerList HANDLERS = new HandlerList();
private final Plot plot;
private static final HandlerList HANDLERS = new HandlerList();
private final Plot plot;
public BBPlayerPlotReceiveEvent(BaseArena eventArena, Plot plot) {
super(eventArena);
this.plot = plot;
}
public PlotPlayerReceiveEvent(BaseArena eventArena, Plot plot) {
public static HandlerList getHandlerList() {
return HANDLERS;
}
super(eventArena);
this.plot = plot;
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
public Plot getPlot() {
return plot;
}
public Plot getPlot() {
return plot;
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,8 +18,7 @@
*
*/
/**
* All arena in-game related events.
*/
package plugily.projects.buildbattle.api.event.plot;
package plugily.projects.buildbattle.api.event.game;
public class PlotReportEvent {
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,37 +21,45 @@
package plugily.projects.buildbattle.api.event.plot;
import org.bukkit.event.HandlerList;
import plugily.projects.buildbattle.api.event.BBEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.minigamesbox.api.events.PlugilyEvent;
/**
* @author Plajer
* @since 4.0.0-pre-12
* <p>
* Called when plot is being reset
* <p>
* Called when plot is being reset
*/
public class BBPlotResetEvent extends BBEvent {
public class PlotResetEvent extends PlugilyEvent {
private static final HandlerList HANDLERS = new HandlerList();
private final Plot plot;
private static final HandlerList HANDLERS = new HandlerList();
private final Plot plot;
public BBPlotResetEvent(BaseArena eventArena, Plot plot) {
super(eventArena);
this.plot = plot;
}
public PlotResetEvent(BaseArena eventArena, Plot plot) {
public static HandlerList getHandlerList() {
return HANDLERS;
}
super(eventArena);
this.plot = plot;
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
}
public Plot getPlot() {
return plot;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
public Plot getPlot() {
return plot;
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
File diff suppressed because it is too large. Load diff
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,387 +21,240 @@
package plugily.projects.buildbattle.arena;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import plugily.projects.buildbattle.ConfigPreferences;
import org.jetbrains.annotations.NotNull;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.api.StatsStorage;
import plugily.projects.buildbattle.api.event.game.BBGameEndEvent;
import plugily.projects.buildbattle.api.event.game.BBGameJoinEvent;
import plugily.projects.buildbattle.api.event.game.BBGameLeaveEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.impl.GuessTheBuildArena;
import plugily.projects.buildbattle.arena.impl.SoloArena;
import plugily.projects.buildbattle.arena.impl.TeamArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.handlers.ChatManager;
import plugily.projects.buildbattle.handlers.PermissionManager;
import plugily.projects.buildbattle.handlers.items.SpecialItem;
import plugily.projects.buildbattle.handlers.party.GameParty;
import plugily.projects.buildbattle.user.User;
import plugily.projects.buildbattle.utils.Debugger;
import plugily.projects.commonsbox.minecraft.compat.VersionUtils;
import plugily.projects.commonsbox.minecraft.misc.MiscUtils;
import plugily.projects.commonsbox.minecraft.misc.stuff.ComplementAccessor;
import plugily.projects.commonsbox.minecraft.serialization.InventorySerializer;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArenaManager;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import java.util.concurrent.ThreadLocalRandom;
import java.util.List;
/**
* @author Plajer
* <p>
* Created at 25.05.2018
* <p>
* Created at 13.05.2018
*/
public class ArenaManager {
public class ArenaManager extends PluginArenaManager {
private static final Main plugin = JavaPlugin.getPlugin(Main.class);
private final Main plugin;
private ArenaManager() {
}
public ArenaManager(Main plugin) {
/**
* Attempts player to join arena.
* Calls BBGameJoinEvent.
* Can be cancelled only via above-mentioned event
*
* @param player player to join
* @param arena arena to join
* @see BBGameJoinEvent
*/
public static void joinAttempt(Player player, BaseArena arena) {
Debugger.debug("Initial join attempt, " + player.getName());
BBGameJoinEvent bbGameJoinEvent = new BBGameJoinEvent(player, arena);
Bukkit.getPluginManager().callEvent(bbGameJoinEvent);
super(plugin);
this.plugin = plugin;
ChatManager chatManager = plugin.getChatManager();
if(!arena.isReady()) {
player.sendMessage(chatManager.getPrefix() + chatManager.colorMessage("In-Game.Arena-Not-Configured"));
return;
}
if(bbGameJoinEvent.isCancelled()) {
player.sendMessage(chatManager.getPrefix() + chatManager.colorMessage("In-Game.Join-Cancelled-Via-API"));
return;
@Override
public void joinAttempt(@NotNull Player player, @NotNull IPluginArena arena) {
if (!plugin.getArenaRegistry().isInArena(player)) {
plugin.savePreJoinLocation(player);
}
// Suspend GameModeInventories swapping before MiniGamesBox takes over
// this player's inventory and gamemode. Lifted again on arena leave, or
// immediately below when the join is refused.
plugin.getBuilderCreativeManager().enterArena(player);
super.joinAttempt(player, arena);
if (!plugin.getArenaRegistry().isInArena(player)) {
plugin.getBuilderCreativeManager().revoke(player);
}
}
if(ArenaRegistry.getArena(player) != null) {
player.sendMessage(chatManager.getPrefix() + chatManager.colorMessage("In-Game.Messages.Already-Playing"));
return;
}
Plot partyPlot = null;
//check if player is in party and send party members to the game
if(plugin.getPartyHandler().isPlayerInParty(player)) {
Debugger.debug("[Party] Initialized party check " + player.getName());
GameParty party = plugin.getPartyHandler().getParty(player);
if(party.getLeader() == player) {
if(arena.getMaximumPlayers() - arena.getPlayers().size() >= party.getPlayers().size()) {
partyPlot = arena.getPlotManager().getPlots().get(ThreadLocalRandom.current().nextInt(arena.getPlotManager().getPlots().size()));
for(Player partyPlayer : party.getPlayers()) {
if(partyPlayer == player) {
continue;
@Override
public void additionalPartyJoin(Player player, IPluginArena arena, Player partyLeader) {
BaseArena pluginArena = plugin.getArenaRegistry().getArena(arena.getId());
if (pluginArena == null) {
return;
}
List<Plot> plots = pluginArena.getPlotManager().getPlots();
Plot partyPlot = plots.get(plots.size() == 1 ? 0 : plugin.getRandom().nextInt(plots.size()));
if (arena.getPlayersLeft().contains(partyLeader)) {
Plot partyLeaderPlot = pluginArena.getPlotManager().getPlot(partyLeader);
if (partyLeaderPlot != null) {
partyPlot = partyLeaderPlot;
}
BaseArena partyPlayerArena = ArenaRegistry.getArena(partyPlayer);
if(partyPlayerArena != null) {
if(partyPlayerArena.getArenaState() == ArenaState.IN_GAME) {
continue;
}
Debugger.debug("[Party] Remove party member " + partyPlayer.getName() + " from other not ingame arena " + player.getName());
leaveAttempt(partyPlayer, partyPlayerArena);
}
partyPlayer.sendMessage(chatManager.getPrefix() + chatManager.formatMessage(arena, chatManager.colorMessage("In-Game.Join-As-Party-Member"), partyPlayer));
joinAttempt(partyPlayer, arena);
Debugger.debug("[Party] Added party member " + partyPlayer.getName() + " to arena of " + player.getName());
}
} else {
player.sendMessage(chatManager.getPrefix() + chatManager.formatMessage(arena, chatManager.colorMessage("In-Game.Messages.Lobby-Messages.Not-Enough-Space-For-Party"), player));
Debugger.debug("[Party] Not enough space for party of " + player.getName());
return;
}
}
Player partyLeader = party.getLeader();
if(arena.getPlayers().contains(partyLeader)) {
Plot partyLeaderPlot = arena.getPlotManager().getPlot(partyLeader);
if(partyLeaderPlot != null) {
partyPlot = partyLeaderPlot;
if (partyPlot != null) {
partyPlot.addMember(player, pluginArena, false);
}
}
Debugger.debug("[Party] Party check done for " + player.getName());
}
//Arena join permission when bungee false
if(!plugin.getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED) &&
(!(player.hasPermission(PermissionManager.getJoinPerm().replace("<arena>", "*"))
|| player.hasPermission(PermissionManager.getJoinPerm().replace("<arena>", arena.getID()))))) {
player.sendMessage(chatManager.getPrefix() + chatManager.colorMessage("In-Game.Join-No-Permission")
.replace("%permission%", PermissionManager.getJoinPerm().replace("<arena>", arena.getID())));
return;
}
if((arena.getArenaState() == ArenaState.IN_GAME || arena.getArenaState() == ArenaState.ENDING)
&& plugin.getConfigPreferences().getOption(ConfigPreferences.Option.DISABLE_SPECTATORS)) {
return;
}
@Override
public void leaveAttempt(@NotNull Player player, @NotNull IPluginArena arena) {
if(arena.getArenaState() == ArenaState.RESTARTING) {
if(plugin.getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
ComplementAccessor.getComplement().kickPlayer(player, chatManager.getPrefix() + chatManager.colorMessage("Commands.Arena-Restarting"));
} else {
player.sendMessage(chatManager.getPrefix() + chatManager.colorMessage("Commands.Arena-Restarting"));
}
return;
}
BaseArena pluginArena = plugin.getArenaRegistry().getArena(arena.getId());
if (pluginArena == null) {
return;
if(arena.getArenaState() == ArenaState.STARTING && arena.getPlayers().size() >= arena.getMaximumPlayers()) {
if(!player.hasPermission(PermissionManager.getJoinFullGames())) {
player.sendMessage(chatManager.getPrefix() + chatManager.colorMessage("In-Game.Full-Game-No-Permission"));
return;
}
boolean foundSlot = false;
for(Player loopPlayer : arena.getPlayers()) {
if(loopPlayer.hasPermission(PermissionManager.getJoinFullGames())) {
continue;
}
leaveAttempt(loopPlayer, arena);
loopPlayer.sendMessage(chatManager.getPrefix() + chatManager.colorMessage("In-Game.Messages.Lobby-Messages.You-Were-Kicked-For-Premium-Slot"));
chatManager.broadcast(arena, chatManager.formatMessage(arena, chatManager.colorMessage("In-Game.Messages.Lobby-Messages.Kicked-For-Premium-Slot"), loopPlayer));
foundSlot = true;
break;
}
if(!foundSlot) {
player.sendMessage(chatManager.getPrefix() + chatManager.colorMessage("In-Game.No-Slots-For-Premium"));
return;
}
}
Debugger.debug("Final join attempt, " + player.getName());
User user = plugin.getUserManager().getUser(player);
user.lastBoard = player.getScoreboard();
//reset scoreboard
player.setScoreboard(Bukkit.getScoreboardManager().getNewScoreboard());
super.leaveAttempt(player, arena);
// After the MiniGamesBox inventory restore, so GameModeInventories-OG
// cannot swap inventories mid-restore.
plugin.getBuilderCreativeManager().revoke(player);
IUser user = plugin.getUserManager().getUser(player);
user.setStatistic("LOCAL_POINTS", 0);
user.setStatistic("LOCAL_POINTS_GTB", 0);
Plot plot = pluginArena.getPlotManager().getPlot(player);
if (plot == null) {
arena.getScoreboardManager().createScoreboard(user);
if(plugin.getConfigPreferences().getOption(ConfigPreferences.Option.INVENTORY_MANAGER_ENABLED)) {
InventorySerializer.saveInventoryToFile(plugin, player);
}
return;
player.setExp(1);
player.setFoodLevel(20);
player.setHealth(VersionUtils.getMaxHealth(player));
player.setLevel(0);
player.setWalkSpeed(0.2f);
player.setFlySpeed(0.1f);
arena.doBarAction(BaseArena.BarAction.ADD, player);
player.getInventory().clear();
player.getInventory().setArmorContents(new ItemStack[]{new ItemStack(Material.AIR), new ItemStack(Material.AIR), new ItemStack(Material.AIR), new ItemStack(Material.AIR)});
//Set player as spectator as the game is already started
if(arena.getArenaState() == ArenaState.IN_GAME || arena.getArenaState() == ArenaState.ENDING) {
arena.addSpectator(player);
player.teleport(arena.getPlotManager().getPlots().get(0).getTeleportLocation());
player.sendMessage(chatManager.colorMessage("In-Game.Spectator.You-Are-Spectator"));
player.getInventory().clear();
for(SpecialItem item : plugin.getSpecialItemsManager().getSpecialItems()) {
if(item.getDisplayStage() != SpecialItem.DisplayStage.SPECTATOR) {
continue;
}
player.getInventory().setItem(item.getSlot(), item.getItemStack());
}
player.getActivePotionEffects().forEach(potionEffect -> player.removePotionEffect(potionEffect.getType()));
player.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, Integer.MAX_VALUE, 0));
//Hide player from other players
arena.getPlayers().forEach(onlinePlayer -> VersionUtils.hidePlayer(plugin, onlinePlayer, player));
user.setSpectator(true);
VersionUtils.setCollidable(player, false);
player.setGameMode(GameMode.ADVENTURE);
player.setAllowFlight(true);
player.setFlying(true);
for(Player spectator : arena.getPlayers()) {
if(plugin.getUserManager().getUser(spectator).isSpectator()) {
VersionUtils.showPlayer(plugin, player, spectator);
} else {
VersionUtils.hidePlayer(plugin, spectator, player);
}
}
return;
}
if(partyPlot != null) {
partyPlot.addMember(player, arena, false);
}
arena.addPlayer(player);
arena.teleportToLobby(player);
if(arena.getArenaState() == ArenaState.STARTING || arena.getArenaState() == ArenaState.WAITING_FOR_PLAYERS) {
for(SpecialItem item : plugin.getSpecialItemsManager().getSpecialItems()) {
if(arena.getArenaType() == BaseArena.ArenaType.TEAM && item.getDisplayStage() == SpecialItem.DisplayStage.TEAM) {
player.getInventory().setItem(item.getSlot(), item.getItemStack());
continue;
}
if(item.getDisplayStage() != SpecialItem.DisplayStage.LOBBY) {
continue;
}
player.getInventory().setItem(item.getSlot(), item.getItemStack());
}
}
player.updateInventory();
chatManager.broadcastAction(arena, player, ChatManager.ActionType.JOIN);
VersionUtils.sendTitles(player, chatManager.colorMessage("In-Game.Messages.Join-Title").replace("%ARENANAME%", arena.getMapName()),
chatManager.colorMessage("In-Game.Messages.Join-SubTitle").replace("%ARENANAME%", arena.getMapName()), 5, 40, 5);
plugin.getSignManager().updateSigns();
}
/**
* Attempts player to leave arena.
* Calls BBGameLeaveEvent event.
*
* @param player player to leave
* @param arena arena to leave
* @see BBGameLeaveEvent
*/
public static void leaveAttempt(Player player, BaseArena arena) {
Debugger.debug("Initial leave attempt, " + player.getName());
Bukkit.getPluginManager().callEvent(new BBGameLeaveEvent(player, arena));
arena.teleportToEndLocation(player);
arena.doBarAction(BaseArena.BarAction.REMOVE, player);
player.getActivePotionEffects().forEach(effect -> player.removePotionEffect(effect.getType()));
VersionUtils.setMaxHealth(player, 20);
player.getInventory().clear();
player.getInventory().setArmorContents(null);
player.resetPlayerTime();
player.resetPlayerWeather();
player.setAllowFlight(false);
player.setExp(0);
player.setFireTicks(0);
player.setFlying(false);
player.setFoodLevel(20);
player.setLevel(0);
player.setGameMode(GameMode.SURVIVAL);
player.setWalkSpeed(0.2f);
User user = plugin.getUserManager().getUser(player);
user.removeScoreboard(arena);
if(plugin.getConfigPreferences().getOption(ConfigPreferences.Option.INVENTORY_MANAGER_ENABLED)) {
InventorySerializer.loadInventory(plugin, player);
}
for(Player onlinePlayer : plugin.getServer().getOnlinePlayers()) {
if(ArenaRegistry.getArena(onlinePlayer) == null) {
VersionUtils.showPlayer(plugin, onlinePlayer, player);
}
VersionUtils.showPlayer(plugin, player, onlinePlayer);
}
// Spectator
if(user.isSpectator() || arena.getSpectators().contains(player)) {
arena.removeSpectator(player);
user.setSpectator(false);
return;
}
Plot plot = arena.getPlotManager().getPlot(player);
if(plot != null) {
if(arena instanceof SoloArena) {
if(plot.getMembers().size() <= 1) {
((SoloArena) arena).getQueue().remove(plot);
}
}
}
arena.removePlayer(player);
plugin.getChatManager().broadcastAction(arena, player, ChatManager.ActionType.LEAVE);
// Games played +1
if(arena.getArenaState() == ArenaState.IN_GAME || arena.getArenaState() == ArenaState.ENDING) {
user.addStat(StatsStorage.StatisticType.GAMES_PLAYED, 1);
}
user.setStat(StatsStorage.StatisticType.LOCAL_GUESS_THE_BUILD_POINTS, 0);
if(plot != null) {
if(arena instanceof TeamArena) {
plot.getMembers().remove(player);
if(plot.getMembers().size() < 1) {
plot.fullyResetPlot();
if (arena instanceof BuildArena) {
if (plot.getMembers().isEmpty()) {
((BuildArena) arena).getQueue().remove(plot);
}
}
} else
plot.fullyResetPlot();
}
if(arena instanceof GuessTheBuildArena) {
((GuessTheBuildArena) arena).getWhoGuessed().remove(player);
}
if(arena.getArenaState() != ArenaState.WAITING_FOR_PLAYERS && arena.getPlayers().isEmpty()) {
arena.setArenaState(ArenaState.RESTARTING);
arena.setTimer(0);
}
if (arena instanceof GuessArena) {
plugin.getSignManager().updateSigns();
}
GuessArena guessArena = (GuessArena) pluginArena;
((GuessArena) arena).getWhoGuessed().remove(player);
if (guessArena.getCurrentBuilders().contains(player)) {
if (plot.getMembers().isEmpty()) {
if (arena.getArenaState() == IArenaState.IN_GAME) {
// ToDo message force skipped
pluginArena.setTimer(
plugin.getConfig().getInt(
"Time-Manager." + pluginArena.getArenaType().getPrefix() + ".Round-Delay"),
true);
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.PLOT_VOTING);
}
}
}
/**
* Stops current arena. Calls BBGameEndEvent event
*
* @param quickStop should arena be stopped immediately? (use only in important cases)
* @param arena arena to stop
* @see BBGameEndEvent
*/
public static void stopGame(boolean quickStop, BaseArena arena) {
Debugger.debug("Game stop event initiate, arena " + arena.getID());
Bukkit.getPluginManager().callEvent(new BBGameEndEvent(arena));
if(!quickStop) {
for(Player player : arena.getPlayers()) {
spawnFireworks(arena, player);
for(SpecialItem item : plugin.getSpecialItemsManager().getSpecialItems()) {
if(item.getDisplayStage() != SpecialItem.DisplayStage.SPECTATOR) {
continue;
}
player.getInventory().setItem(item.getSlot(), item.getItemStack());
}
User user = plugin.getUserManager().getUser(player);
user.removeScoreboard(arena);
}
}
arena.getScoreboardManager().stopAllScoreboards();
arena.setArenaState(ArenaState.ENDING);
arena.setTimer(10);
if(arena instanceof SoloArena) {
((SoloArena) arena).setVoting(false);
}
Debugger.debug("Game stop event finish, arena " + arena.getID());
}
private static void spawnFireworks(BaseArena arena, Player player) {
if(!plugin.getConfig().getBoolean("Firework-When-Game-Ends", true)) {
return;
}
new BukkitRunnable() {
int i = 0;
@Override
public void run() {
if(i == 4 || !arena.getPlayers().contains(player)) {
cancel();
return;
public void hubLeaveAttempt(@NotNull Player player, @NotNull BaseArena pluginArena) {
plugin.getDebugger().debug("[{0}] Hub leave attempt for {1}", pluginArena.getId(), player.getName());
IUser user = plugin.getUserManager().getUser(player);
if (user != null) {
plugin.getUserManager().saveAllStatistic(user);
user.setStatistic("LOCAL_POINTS", 0);
user.setStatistic("LOCAL_POINTS_GTB", 0);
user.setSpectator(false);
user.setPermanentSpectator(false);
pluginArena.getScoreboardManager().removeScoreboard(user);
}
MiscUtils.spawnRandomFirework(player.getLocation());
i++;
}
}.runTaskTimer(plugin, 30, 30);
}
restoreVisibility(player);
player.closeInventory();
pluginArena.removeSpectatorPlayer(player);
pluginArena.getBossbarManager().doBarAction(IPluginArena.IBarAction.REMOVE, player);
pluginArena.getPlayers().remove(player);
plugin.getActionBarManager().clearActionBarsFromPlayer(player);
removePlotMembership(player, pluginArena);
if (shouldStopAfterHubLeave(pluginArena)) {
stopGame(true, pluginArena);
}
plugin.getSignManager().updateSigns();
plugin.getDebugger().debug("[{0}] Hub leave complete for {1}", pluginArena.getId(), player.getName());
}
private void restoreVisibility(Player player) {
for (Player online : Bukkit.getOnlinePlayers()) {
VersionUtils.showPlayer(plugin, player, online);
if (plugin.getArenaRegistry().getArena(online) == null) {
VersionUtils.showPlayer(plugin, online, player);
}
}
}
private void removePlotMembership(Player player, BaseArena pluginArena) {
Plot plot = pluginArena.getPlotManager().getPlot(player);
pluginArena.getPlotList().remove(player);
if (plot == null) {
return;
}
plot.removeMember(player);
if (pluginArena instanceof BuildArena && plot.getMembers().isEmpty()) {
((BuildArena) pluginArena).getQueue().remove(plot);
}
if (pluginArena instanceof GuessArena) {
GuessArena guessArena = (GuessArena) pluginArena;
guessArena.getWhoGuessed().remove(player);
boolean currentBuilder = guessArena.getCurrentBuilders().remove(player);
if (currentBuilder && plot.getMembers().isEmpty() && pluginArena.getArenaState() == IArenaState.IN_GAME) {
pluginArena.setTimer(plugin.getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".Round-Delay"), true);
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.PLOT_VOTING);
}
}
}
private boolean shouldStopAfterHubLeave(BaseArena pluginArena) {
IArenaState state = pluginArena.getArenaState();
return pluginArena.getPlayers().isEmpty() && state != IArenaState.FULL_GAME
&& state != IArenaState.WAITING_FOR_PLAYERS && state != IArenaState.STARTING;
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,223 +21,301 @@
package plugily.projects.buildbattle.arena;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.impl.GuessTheBuildArena;
import plugily.projects.buildbattle.arena.impl.SoloArena;
import plugily.projects.buildbattle.arena.impl.TeamArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.utils.Debugger;
import plugily.projects.commonsbox.minecraft.compat.ServerVersion.Version;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.commonsbox.minecraft.dimensional.Cuboid;
import plugily.projects.commonsbox.minecraft.serialization.LocationSerializer;
import plugily.projects.buildbattle.handlers.misc.ArenaWorldProvisioner;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.PluginArenaRegistry;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.minigamesbox.classic.utils.dimensional.Cuboid;
import plugily.projects.minigamesbox.classic.utils.serialization.LocationSerializer;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Locale;
/**
* Created by Tom on 27/07/2014.
*/
public class ArenaRegistry {
public class ArenaRegistry extends PluginArenaRegistry {
private static final List<BaseArena> ARENAS = new ArrayList<>();
private static final Main plugin = JavaPlugin.getPlugin(Main.class);
private final Main plugin;
private static int bungeeArena = -999;
public ArenaRegistry(Main plugin) {
public static List<BaseArena> getArenas() {
return ARENAS;
}
super(plugin);
this.plugin = plugin;
/**
* Returns arena where the player is
*
* @param p target player
* @return Arena or null if not playing
*/
@Nullable
public static BaseArena getArena(Player p) {
if(p == null) {
return null;
}
java.util.UUID playerId = p.getUniqueId();
// Skips arenas with unloaded worlds: MiniGamesBox would createWorld() them.
@Override
public void registerArena(String id) {
for(BaseArena arena : ARENAS) {
for(Player player : arena.getPlayers()) {
if(playerId.equals(player.getUniqueId())) return arena;
}
for(Player player : arena.getSpectators()) {
if(playerId.equals(player.getUniqueId())) return arena;
}
}
return null;
}
ArenaWorldProvisioner provisioner = plugin.getArenaWorldProvisioner();
for (String worldName : ArenaWorldProvisioner.collectArenaWorlds(ConfigUtils.getConfig(plugin, "arenas"), id)
.keySet())
{
public static void registerArena(BaseArena arena) {
Debugger.debug("Registering new game instance, " + arena.getID());
ARENAS.add(arena);
}
if (plugin.getMyWorldsManager().isProtectedWorld(worldName)) {
public static void unregisterArena(BaseArena arena) {
Debugger.debug("Unegistering game instance, " + arena.getID());
ARENAS.remove(arena);
}
// additionalValidatorChecks reports this one.
continue;
/**
* Returns arena based by ID
*
* @param id name of arena
* @return Arena or null if not found
*/
public static BaseArena getArena(String id) {
for(BaseArena arena : ARENAS) {
if(arena.getID().equalsIgnoreCase(id)) {
return arena;
}
}
return null;
}
public static int getArenaPlayersOnline() {
int players = 0;
for(BaseArena arena : ARENAS) {
players += arena.getPlayers().size();
}
return players;
}
public static void registerArenas() {
Debugger.debug("Initial arenas registration");
ArenaRegistry.getArenas().clear();
ConfigurationSection section = ConfigUtils.getConfig(plugin, "arenas").getConfigurationSection("instances");
if(section == null) {
Debugger.debug(Debugger.Level.WARN, "No instances configuration section in arenas.yml, skipping registration process! Was it manually edited?");
return;
}
for(String id : section.getKeys(false)) {
if(id.equalsIgnoreCase("default")) {
continue;
}
BaseArena.ArenaType arenaType;
try {
arenaType = BaseArena.ArenaType.valueOf(section.getString(id + ".gametype", "solo").toUpperCase());
} catch(IllegalArgumentException e) {
arenaType = BaseArena.ArenaType.SOLO;
}
BaseArena arena;
switch(arenaType) {
case TEAM:
arena = new TeamArena(id, plugin);
break;
case GUESS_THE_BUILD:
arena = new GuessTheBuildArena(id, plugin);
break;
case SOLO:
default:
arena = new SoloArena(id, plugin);
break;
}
if(section.contains(id + ".minimumplayers")) {
arena.setMinimumPlayers(section.getInt(id + ".minimumplayers"));
} else {
arena.setMinimumPlayers(section.getInt("instances.default.minimumplayers"));
}
if(section.contains(id + ".maximumplayers")) {
arena.setMaximumPlayers(section.getInt(id + ".maximumplayers"));
} else {
arena.setMaximumPlayers(section.getInt("instances.default.maximumplayers"));
}
if(section.contains(id + ".mapname")) {
arena.setMapName(section.getString(id + ".mapname"));
} else {
arena.setMapName(section.getString("instances.default.mapname"));
}
Location lobbyLoc = LocationSerializer.getLocation(section.getString(id + ".lobbylocation"));
if(lobbyLoc == null || lobbyLoc.getWorld() == null) {
arena.setReady(false);
continue;
}
arena.setLobbyLocation(lobbyLoc);
if(section.contains(id + ".Endlocation")) {
arena.setEndLocation(LocationSerializer.getLocation(section.getString(id + ".Endlocation")));
} else if(!plugin.getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
System.out.print(id + " doesn't contains an end location!");
arena.setReady(false);
ArenaRegistry.registerArena(arena);
continue;
}
arena.setArenaType(arenaType);
arena.setPlotSize(section.getInt(id + ".plotSize", 2));
ConfigurationSection plotSection = section.getConfigurationSection(id + ".plots");
if(plotSection != null) {
for(String plotName : plotSection.getKeys(false)) {
String minPointString = plotSection.getString(plotName + ".minpoint");
String maxPointString = plotSection.getString(plotName + ".maxpoint");
if(minPointString != null && maxPointString != null) {
Location minPoint = LocationSerializer.getLocation(minPointString);
if(minPoint != null) {
org.bukkit.World minWorld = minPoint.getWorld();
if(minWorld != null) {
Biome biome = Version.isCurrentHigher(Version.v1_15_R1) ?
minWorld.getBiome(minPoint.getBlockX(), minPoint.getBlockY(), minPoint.getBlockZ())
: minWorld.getBiome(minPoint.getBlockX(), minPoint.getBlockZ());
Plot buildPlot = new Plot(arena, biome);
buildPlot.setCuboid(new Cuboid(minPoint, LocationSerializer.getLocation(maxPointString)));
buildPlot.fullyResetPlot();
arena.getPlotManager().addBuildPlot(buildPlot);
}
}
} else {
System.out.println("Non configured plot instances found for arena " + id);
arena.setReady(false);
}
if (provisioner == null || !provisioner.isWorldAvailable(worldName)) {
plugin.getLogger().severe("Arena " + id + " is not registered: its world '" + worldName
+ "' is not loaded and could not be loaded from disk, and registering it anyway would let"
+ " MiniGamesBox generate a vanilla world named '" + worldName + "' in its place.");
return;
}
}
} else {
System.out.println("Non configured plots in arena " + id);
arena.setReady(false);
}
arena.setReady(section.getBoolean(id + ".isdone"));
if(arena instanceof SoloArena) {
((SoloArena) arena).initPoll();
}
ArenaRegistry.registerArena(arena);
arena.start();
}
Debugger.debug("Arenas registration completed");
}
public static void shuffleBungeeArena() {
bungeeArena = new Random().nextInt(ARENAS.size());
}
super.registerArena(id);
public static int getBungeeArena() {
if(bungeeArena == -999) {
bungeeArena = new Random().nextInt(ARENAS.size());
}
return bungeeArena;
}
@Override
public PluginArena getNewArena(String id) {
switch (ConfigUtils.getConfig(plugin, "arenas").getString("instances." + id + ".gametype", "classic")
.toLowerCase(Locale.ENGLISH))
{
case "gtb":
case "guessthebuild":
case "guess_the_build":
return new GuessArena(id);
case "classic":
case "solo":
case "team":
default:
return new BuildArena(id);
}
}
@Override
public boolean additionalValidatorChecks(ConfigurationSection section, PluginArena arena, String id) {
if (!super.additionalValidatorChecks(section, arena, id))
return false;
boolean isBuildArena = arena instanceof BuildArena;
boolean isGuessArena = arena instanceof GuessArena;
String arenaPath = id + ".";
if (!plugin.getMyWorldsManager().requireConfiguredArenaWorld(
plugin.getMyWorldsManager().getWorldName(section.getString(arenaPath + "lobbylocation")),
"Lobby location", (BaseArena) arena))
{
return false;
}
if (!plugin.getMyWorldsManager().requireConfiguredArenaWorld(
plugin.getMyWorldsManager().getWorldName(section.getString(arenaPath + "startlocation")),
"Start location", (BaseArena) arena))
{
return false;
}
if (!plugin.getMyWorldsManager().requireConfiguredArenaWorld(
plugin.getMyWorldsManager().getWorldName(section.getString(arenaPath + "endlocation")), "End location",
(BaseArena) arena))
{
return false;
}
if (isBuildArena) {
int plotMemberSize = section.getInt(id + ".plotmembersize", 0);
// Member size can not be less than 1
if (plotMemberSize < 1) {
plugin.getDebugger().sendConsoleMsg(new MessageBuilder("VALIDATOR_INVALID_ARENA_CONFIGURATION").asKey()
.value("INVALID PLOT MEMBER SIZE!").arena(arena).build());
return false;
}
arena.setArenaOption("PLOT_MEMBER_SIZE", plotMemberSize);
int minPlayers = arena.getArenaOption("MINIMUM_PLAYERS");
if (minPlayers <= plotMemberSize) {
arena.setArenaOption("MINIMUM_PLAYERS", plotMemberSize + 1);
plugin.getDebugger().sendConsoleMsg(new MessageBuilder("VALIDATOR_INVALID_ARENA_CONFIGURATION").asKey()
.value("MIN PLAYERS NEEDS TO BE 1 MORE THAN PLOT_MEMBER_SIZE, AUTOMATICALLY ADJUSTED. CONFIRM BY CHECKING ARENA SETUP!")
.arena(arena).build());
}
((BuildArena) arena).setTypeByPlotMembers();
} else {
// todo gtb team mode, because why not!
arena.setArenaOption("PLOT_MEMBER_SIZE", 1);
}
ConfigurationSection plotSection = section.getConfigurationSection(id + ".plots");
if (plotSection == null) {
plugin.getDebugger().sendConsoleMsg(new MessageBuilder("VALIDATOR_INVALID_ARENA_CONFIGURATION").asKey()
.value("PLOTS SETUP MISSING!").arena(arena).build());
return false;
}
BaseArena baseArena = (BaseArena) arena;
for (String plotName : plotSection.getKeys(false)) {
String minPointString = plotSection.getString(plotName + ".1", null);
String maxPointString = plotSection.getString(plotName + ".2", null);
if (minPointString != null && maxPointString != null) {
if (!plugin.getMyWorldsManager().validateArenaWorld(
plugin.getMyWorldsManager().getWorldName(minPointString), "Plot " + plotName + " corner 1",
baseArena)
|| !plugin.getMyWorldsManager().validateArenaWorld(
plugin.getMyWorldsManager().getWorldName(maxPointString),
"Plot " + plotName + " corner 2", baseArena))
{
return false;
}
Location minPoint = LocationSerializer.getLocation(minPointString);
Location maxPoint = LocationSerializer.getLocation(maxPointString);
if (minPoint != null && maxPoint != null) {
World minWorld = minPoint.getWorld();
if (minWorld != null) {
Biome biome = ServerVersion.Version.isCurrentHigher(ServerVersion.Version.v1_15)
? minWorld.getBiome(minPoint.getBlockX(), minPoint.getBlockY(), minPoint.getBlockZ())
: minWorld.getBiome(minPoint.getBlockX(), minPoint.getBlockZ());
Plot buildPlot = new Plot(baseArena, biome);
buildPlot.setCuboid(new Cuboid(minPoint, maxPoint));
buildPlot.fullyResetPlot();
if (isGuessArena) {
int plotMemberSize = arena.getArenaOption("PLOT_MEMBER_SIZE");
int maxPlayers = arena.getMaximumPlayers();
int plotAmount = maxPlayers / plotMemberSize;
for (int i = 0; i < plotAmount; i++) {
Plot copyBuildPlot = new Plot(baseArena, biome);
copyBuildPlot.setCuboid(new Cuboid(minPoint, maxPoint));
copyBuildPlot.fullyResetPlot();
baseArena.getPlotManager().addBuildPlot(copyBuildPlot);
}
break;
} else {
baseArena.getPlotManager().addBuildPlot(buildPlot);
}
}
}
} else {
plugin.getDebugger().sendConsoleMsg(new MessageBuilder("VALIDATOR_INVALID_ARENA_CONFIGURATION").asKey()
.value("PLOT NOT CONFIGURED!").arena(arena).build());
return false;
}
}
if (isBuildArena) {
((BuildArena) arena).initPoll();
}
return true;
}
@Override
public @Nullable BaseArena getArena(Player player) {
IPluginArena pluginArena = super.getArena(player);
if (pluginArena instanceof BaseArena) {
return (BaseArena) pluginArena;
}
return null;
}
@Override
public @Nullable BaseArena getArena(String id) {
IPluginArena pluginArena = super.getArena(id);
if (pluginArena instanceof BaseArena) {
return (BaseArena) pluginArena;
}
return null;
}
public @NotNull List<BaseArena> getPluginArenas() {
List<BaseArena> baseArenas = new ArrayList<>(super.getArenas().size());
for (IPluginArena pluginArena : super.getArenas()) {
if (pluginArena instanceof BaseArena) {
baseArenas.add((BaseArena) pluginArena);
}
}
return baseArenas;
}
}
@@ -1,50 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena;
import org.bukkit.plugin.java.JavaPlugin;
import plugily.projects.buildbattle.Main;
/**
* @author TomTheDeveloper
* <p>
* Contains all GameStates.
*/
public enum ArenaState {
WAITING_FOR_PLAYERS("Waiting"), STARTING("Starting"), IN_GAME("In-Game"), ENDING("Ending"), RESTARTING("Restarting");
private final String formattedName;
private final String placeholder;
ArenaState(String formattedName) {
this.formattedName = formattedName;
this.placeholder = JavaPlugin.getPlugin(Main.class).getChatManager().colorMessage("Placeholders.Game-States." + formattedName);
}
public String getFormattedName() {
return formattedName;
}
public String getPlaceholder() {
return placeholder;
}
}
@@ -1,68 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.impl.SoloArena;
/**
* @author Tigerpanzer_02
* <p>
* Created at 18.06.2021
*/
public class ArenaUtils {
private static final Main plugin = JavaPlugin.getPlugin(Main.class);
public static void arenaForceStart(Player player, String theme) {
if(!plugin.getArgumentsRegistry().hasPermission(player, "buildbattle.admin.forcestart")) {
return;
}
BaseArena arena = ArenaRegistry.getArena(player);
if(arena == null) {
player.sendMessage(plugin.getChatManager().getPrefix() + plugin.getChatManager().colorMessage("Commands.No-Playing"));
return;
}
int minPlayers = arena.getMinimumPlayers();
if(arena.getPlayers().size() < minPlayers) {
plugin.getChatManager().broadcast(arena, plugin.getChatManager().colorMessage("In-Game.Messages.Lobby-Messages.Waiting-For-Players").replace("%MINPLAYERS%", Integer.toString(minPlayers)));
return;
}
if(arena.getArenaState() == ArenaState.WAITING_FOR_PLAYERS || arena.getArenaState() == ArenaState.STARTING) {
arena.setArenaState(ArenaState.STARTING);
arena.setForceStart(true);
arena.setTimer(0);
if(!theme.isEmpty() && arena instanceof SoloArena) {
((SoloArena) arena).setThemeVoteTime(false);
arena.setTimer(plugin.getConfigPreferences().getTimer(ConfigPreferences.TimerType.BUILD, arena));
arena.setTheme(theme);
}
plugin.getChatManager().broadcast(arena, plugin.getChatManager().colorMessage("In-Game.Messages.Admin-Messages.Set-Starting-In-To-0"));
}
}
}
@@ -0,0 +1,446 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.managers.MapRestorerManager;
import plugily.projects.buildbattle.arena.managers.PhaseBossbarManager;
import plugily.projects.buildbattle.arena.managers.ScoreboardManager;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.arena.managers.plots.PlotManager;
import plugily.projects.buildbattle.handlers.menu.registry.particles.ParticleRefreshScheduler;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.handlers.reward.RewardType;
import plugily.projects.minigamesbox.classic.handlers.reward.RewardsFactory;
import plugily.projects.minigamesbox.classic.utils.actionbar.ActionBar;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Tigerpanzer_02
* <p>
* Created at 17.12.2021
*/
public class BaseArena extends PluginArena {
private static Main plugin;
private final List<Player> spectators = new ArrayList<>();
private MapRestorerManager mapRestorerManager;
private final PlotManager plotManager;
private final PhaseBossbarManager bossbarManager;
// Seconds the running phase started with; feeds the boss bar's progress.
private int phaseLength;
private String theme = null;
protected ParticleRefreshScheduler particleRefreshScheduler;
private ArenaType arenaType;
private ArenaInGameState arenaInGameState = ArenaInGameState.NONE;
private Map<Player, Plot> plotList = new HashMap<>();
private Plot winnerPlot;
public BaseArena(String id) {
super(id);
setPluginValues();
setScoreboardManager(new ScoreboardManager(this));
mapRestorerManager = new MapRestorerManager(this);
plotManager = new PlotManager(this);
setMapRestorerManager(mapRestorerManager);
bossbarManager = new PhaseBossbarManager(this);
}
// MiniGamesBox adds and removes players through this getter, so the phase
// timer bar replaces its rotating-message bar without touching its field.
@Override
public PhaseBossbarManager getBossbarManager() {
return bossbarManager;
}
// The bar is refreshed after the state handlers so it shows this second.
@Override
public void run() {
super.run();
bossbarManager.bossBarUpdate();
}
public int getPhaseLength() {
return phaseLength;
}
// A timer raised above its current value starts a new phase countdown.
@Override
public void setTimer(int seconds) {
notePhaseTimer(seconds);
super.setTimer(seconds);
}
@Override
public void setTimer(int seconds, boolean forceArenaTimer) {
notePhaseTimer(seconds);
super.setTimer(seconds, forceArenaTimer);
}
private void notePhaseTimer(int seconds) {
if (seconds > getTimer()) {
phaseLength = seconds;
}
}
// A state change adopts whatever timer the new phase was given.
private void resetPhase() {
phaseLength = Math.max(0, getTimer());
}
@Override
public void setArenaState(IArenaState arenaState, boolean forceArenaState) {
final boolean changed = arenaState != getArenaState();
super.setArenaState(arenaState, forceArenaState);
if (changed) {
resetPhase();
}
}
@Override
public void setArenaState(IArenaState arenaState) {
final boolean changed = arenaState != getArenaState();
super.setArenaState(arenaState);
if (changed) {
resetPhase();
}
}
public static void init(Main plugin) {
BaseArena.plugin = plugin;
}
@Override
public Main getPlugin() {
return plugin;
}
@Override
public MapRestorerManager getMapRestorerManager() {
return mapRestorerManager;
}
private void setPluginValues() {
}
public void addSpectatorPlayer(Player player) {
spectators.add(player);
}
public void removeSpectatorPlayer(Player player) {
spectators.remove(player);
}
public boolean isSpectatorPlayer(Player player) {
return spectators.contains(player);
}
public void cleanUpArena() {
spectators.clear();
plotList.clear();
setTheme(null);
winnerPlot = null;
phaseLength = 0;
bossbarManager.removeAll();
}
public List<Player> getSpectators() {
return spectators;
}
public enum ArenaType {
SOLO("Classic"), TEAM("Teams"), GUESS_THE_BUILD("Guess-The-Build");
private final String prefix;
ArenaType(String prefix) {
this.prefix = prefix;
}
public String getPrefix() {
return prefix;
}
}
public enum ArenaInGameState {
THEME_VOTING("Theme-Voting"), BUILD_TIME("Build-Time"), PLOT_VOTING("Plot-Voting"), NONE("NONE");
private final String prefix;
ArenaInGameState(String prefix) {
this.prefix = prefix;
}
public String getPrefix() {
return prefix;
}
}
/**
* Get current arena theme
*
* @return arena theme String or "Theme" as default
*/
@NotNull
public String getTheme() {
return theme;
}
public void setTheme(String arenaTheme) {
this.theme = arenaTheme;
}
public void sendBuildLeftTimeMessage() {
new TitleBuilder("IN_GAME_MESSAGES_PLOT_TIME_LEFT_TITLE").asKey().arena(this).sendArena();
MessageBuilder message = new MessageBuilder("IN_GAME_MESSAGES_PLOT_TIME_LEFT_CHAT").asKey().arena(this);
message.sendArena();
getPlayers().forEach(player -> getPlugin().getActionBarManager().addActionBar(player,
new ActionBar(message, ActionBar.ActionBarType.DISPLAY)));
}
public final void checkPlayerOutSidePlot() {
if (plugin.getConfigPreferences().getOption("PLOT_MOVE_OUTSIDE")) {
return;
}
if (getArenaOption("IN_PLOT_CHECKER") >= 3) {
setArenaOption("IN_PLOT_CHECKER", 0);
for (Player player : getPlayersLeft()) {
if (this instanceof GuessArena) {
Plot buildPlot = ((GuessArena) this).getBuildPlot();
if (buildPlot != null) {
player.setPlayerWeather(buildPlot.getWeatherType());
player.setPlayerTime(Plot.Time.format(buildPlot.getTime(), player.getWorld().getTime()), false);
}
}
// Past the wall by any route: pulled to the nearest legal spot.
plugin.getPlotBorderManager().enforce(player);
}
}
changeArenaOptionBy("IN_PLOT_CHECKER", 1);
}
public void calculateWinnerPlot() {
winnerPlot = plotManager.getTopPlotsOrder().get(0);
}
public void executeEndRewards() {
RewardsFactory rewards = plugin.getRewardsHandler();
RewardType placeRewardType = rewards.getRewardType("PLACE");
List<Plot> plotsRanking = plotManager.getTopPlotsOrder();
plotsRanking.forEach(plot -> plot.getMembers().forEach(
player -> rewards.performReward(player, this, placeRewardType, plotsRanking.indexOf(plot) + 1)));
plugin.getRewardsHandler().performReward(this, plugin.getRewardsHandler().getRewardType("END_GAME"));
}
public void teleportToWinnerPlot() {
Location winnerLocation = winnerPlot.getTeleportLocation();
String formattedMembers = winnerPlot.getFormattedMembers();
for (Player player : getPlayers()) {
VersionUtils.teleport(player, winnerLocation);
new TitleBuilder("IN_GAME_MESSAGES_PLOT_VOTING_WINNER").asKey().player(player).value(formattedMembers)
.sendPlayer();
}
}
public PlotManager getPlotManager() {
return plotManager;
}
public ArenaType getArenaType() {
return arenaType;
}
public void setArenaType(ArenaType arenaType) {
this.arenaType = arenaType;
}
public ArenaInGameState getArenaInGameState() {
return arenaInGameState;
}
public void setArenaInGameState(ArenaInGameState arenaInGameState) {
final boolean changed = arenaInGameState != this.arenaInGameState;
this.arenaInGameState = arenaInGameState;
if (changed) {
resetPhase();
}
}
public ParticleRefreshScheduler getParticleRefreshScheduler() {
return particleRefreshScheduler;
}
public void setParticleRefreshScheduler(ParticleRefreshScheduler particleRefreshScheduler) {
this.particleRefreshScheduler = particleRefreshScheduler;
}
public boolean enoughPlayersToContinue() {
return true;
}
public void distributePlots() {
}
public Map<Player, Plot> getPlotList() {
return plotList;
}
public Plot getPlotFromPlayer(Player player) {
return plotList.get(player);
}
public Plot getWinnerPlot() {
return winnerPlot;
}
public void setWinnerPlot(Plot winnerPlot) {
this.winnerPlot = winnerPlot;
}
}
@@ -0,0 +1,347 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.arena.states.build.InGameState;
import plugily.projects.buildbattle.arena.states.build.StartingState;
import plugily.projects.buildbattle.handlers.themes.ThemeManager;
import plugily.projects.buildbattle.handlers.themes.vote.VoteMenu;
import plugily.projects.buildbattle.handlers.themes.vote.VotePoll;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
/**
* @author Tigerpanzer_02
* <p>
* Created at 22.04.2022
*/
public class BuildArena extends BaseArena {
private final Queue<Plot> queue = new LinkedList<>();
private Plot votingPlot;
private VoteMenu voteMenu;
private int round = 1;
// Themes built so far this match, so no round repeats one.
private final List<String> playedThemes = new ArrayList<>();
public BuildArena(String id) {
super(id);
setArenaType(ArenaType.SOLO);
addGameStateHandler(IArenaState.IN_GAME, new InGameState());
addGameStateHandler(IArenaState.STARTING, new StartingState());
getPlugin().getDebugger().debug("Init Arena {0} with ArenaType {1}", getId(), getArenaType());
}
/**
* Initiates voting poll
*/
public void initPoll() {
voteMenu = new VoteMenu(this);
voteMenu.resetPoll();
}
@Override
public void cleanUpArena() {
votingPlot = null;
queue.clear();
round = 1;
playedThemes.clear();
if (voteMenu != null) {
voteMenu.resetPoll();
}
super.cleanUpArena();
}
public int getRound() {
return round;
}
// Build rounds per match from Time-Manager.<type>.Rounds, never below one.
public int getRounds() {
return Math.max(1, getPlugin().getConfig().getInt("Time-Manager." + getArenaType().getPrefix() + ".Rounds", 3));
}
public boolean isLastRound() {
return round >= getRounds();
}
// Time-Manager.<type>.Random-Theme: the plugin picks each theme, no vote.
public boolean isRandomTheme() {
return getPlugin().getConfig().getBoolean("Time-Manager." + getArenaType().getPrefix() + ".Random-Theme", true);
}
public List<String> getPlayedThemes() {
return playedThemes;
}
// An unused theme from this type's list, or null when the list is empty.
public String pickRandomTheme() {
List<String> themes = new ArrayList<>(
getPlugin().getThemeManager().getThemes(ThemeManager.GameThemes.getByArenaType(getArenaType())));
List<String> unplayed = new ArrayList<>(themes);
unplayed.removeAll(playedThemes);
List<String> pool = unplayed.isEmpty() ? themes : unplayed;
return pool.isEmpty() ? null : pool.get(ThreadLocalRandom.current().nextInt(pool.size()));
}
// Closes the judged round: every occupied plot is cleared for a new theme.
public void nextRound() {
round++;
votingPlot = null;
queue.clear();
setTheme(null);
for (Plot plot : getPlotManager().getPlots()) {
if (plot.getMembers().isEmpty()) {
continue;
}
plot.resetPlot();
plot.resetRoundPoints();
}
if (voteMenu != null) {
voteMenu.resetPoll();
}
}
public VotePoll getVotePoll() {
return voteMenu.getVotePoll();
}
public VoteMenu getVoteMenu() {
return voteMenu;
}
public void setVotingPlot(Plot votingPlot) {
this.votingPlot = votingPlot;
}
public Plot getVotingPlot() {
return votingPlot;
}
@NotNull
public Queue<Plot> getQueue() {
return queue;
}
@Override
public void distributePlots() {
int neededPlots = getPlayersLeft().size() / getArenaOption("PLOT_MEMBER_SIZE");
if (getPlotManager().getPlots().size() < neededPlots) {
getPlugin().getMessageUtils().errorOccurred();
getPlugin().getDebugger().sendConsoleMsg("&c[Build Battle] [PLOT WARNING] Not enough plots in arena "
+ getId() + "! Lacks " + (neededPlots - getPlotManager().getPlots().size()) + " plots");
getPlugin().getDebugger().sendConsoleMsg(
"&c[PLOT WARNING] Required " + neededPlots + " but have " + getPlotManager().getPlots().size());
getPlugin().getDebugger().sendConsoleMsg("&c[PLOT WARNING] Instance was stopped!");
getPlugin().getArenaManager().stopGame(true, this);
}
switch (getArenaType()) {
case SOLO:
List<Player> players = new ArrayList<>(getPlayersLeft());
for (Plot plot : getPlotManager().getPlots()) {
if (players.isEmpty()) {
break;
}
if (!plot.getMembers().isEmpty()) {
continue;
}
if (!getPlugin().getUserManager().getUser(players.get(0)).isSpectator()) {
plot.addMember(players.remove(0), this, true);
}
}
break;
case TEAM:
int plotMemberSize = getArenaOption("PLOT_MEMBER_SIZE");
int neededDividedPlots = getPlayersLeft().size() / plotMemberSize;
int currentDividedPlots = (int) getPlotManager().getPlots().stream()
.filter(plot -> plot.getMembersSize() > 0).count();
if (neededDividedPlots > currentDividedPlots) {
List<Plot> fullPlots = getPlotManager().getPlots().stream()
.filter(plot -> plot.getMembersSize() == plotMemberSize).collect(Collectors.toList());
List<Player> playersToMove = getPlayersLeft().stream()
.filter(player -> fullPlots.stream().noneMatch(plot -> plot.getMembers().contains(player)))
.collect(Collectors.toList());
if (!playersToMove.isEmpty()) {
for (int i = 0; i < playersToMove.size(); i++) {
Player move = playersToMove.get(i);
List<Plot> emptyPlots = getPlotManager().getPlots().stream()
.filter(plot -> plot.getMembersSize() < plotMemberSize)
.collect(Collectors.toList());
Plot maxEmptyPlot = emptyPlots.stream().max(Comparator.comparing(Plot::getMembersSize))
.get();
maxEmptyPlot.addMember(move, this, true);
}
}
}
// check if not only one plot got players
Plot maxPlayers = getPlotManager().getPlots().stream().max(Comparator.comparing(Plot::getMembersSize))
.get();
Plot minPlayers = getPlotManager().getPlots().stream().min(Comparator.comparing(Plot::getMembersSize))
.get();
if (maxPlayers.getMembersSize() == getPlayersLeft().size()) {
for (int i = 0; i < maxPlayers.getMembersSize() / 2; i++) {
Player move = maxPlayers.getMembers().get(i);
minPlayers.addMember(move, this, true);
maxPlayers.removeMember(move);
}
}
}
for (Plot plot : getPlotManager().getPlots()) {
if (plot.getMembers().isEmpty()) {
continue;
}
for (Player member : plot.getMembers()) {
getPlotList().put(member, plot);
}
}
getPlotManager().teleportToPlots();
}
@Override
public boolean enoughPlayersToContinue() {
int size = getPlayersLeft().size();
int memberSize = getArenaOption("PLOT_MEMBER_SIZE");
if (size > memberSize) {
return true;
}
if (size == memberSize) {
return !new HashSet<>(getPlotManager().getPlot(getPlayersLeft().get(0)).getMembers())
.containsAll(getPlayersLeft());
}
return false;
}
@Override
public void setMinimumPlayers(int amount) {
if (getArenaType() == ArenaType.TEAM && amount <= getArenaOption("PLOT_MEMBER_SIZE")) {
getPlugin().getDebugger().debug(
"Minimum players amount for TEAM game mode arena cannot be less than 3! Setting amount to 3!");
super.setMinimumPlayers(3);
return;
}
super.setMinimumPlayers(amount);
}
protected void setTypeByPlotMembers() {
setArenaType(getArenaOption("PLOT_MEMBER_SIZE") <= 1 ? ArenaType.SOLO : ArenaType.TEAM);
}
}
@@ -0,0 +1,358 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.api.event.guess.PlayerThemeGuessEvent;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.arena.states.guess.InGameState;
import plugily.projects.buildbattle.arena.states.guess.StartingState;
import plugily.projects.buildbattle.handlers.themes.GuessTheme;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* @author Tigerpanzer_02
* <p>
* Created at 29.05.2022
*/
public class GuessArena extends BaseArena {
private final List<Player> whoGuessed = new ArrayList<>();
private int round = 1;
private GuessTheme currentTheme = null;
private Plot buildPlot = null;
private List<Integer> removedCharsAt = new ArrayList<>();
private final int plotMemberSize = getArenaOption("PLOT_MEMBER_SIZE");
private List<Plot> playedPlots = new ArrayList<>();
private List<String> playedThemes = new ArrayList<>();
public GuessArena(String id) {
super(id);
setArenaType(ArenaType.GUESS_THE_BUILD);
addGameStateHandler(IArenaState.IN_GAME, new InGameState());
addGameStateHandler(IArenaState.STARTING, new StartingState());
getPlugin().getDebugger().debug("Init Arena {0} with ArenaType {1}", getId(), getArenaType());
}
@Override
public void cleanUpArena() {
currentTheme = null;
resetBuildPlot();
round = 1;
playedPlots.clear();
playedThemes.clear();
super.cleanUpArena();
}
@Override
public void distributePlots() {
int neededPlots = getPlayersLeft().size() / plotMemberSize;
if (getPlotManager().getPlots().size() < neededPlots) {
getPlugin().getMessageUtils().errorOccurred();
getPlugin().getDebugger().sendConsoleMsg("&c[Build Battle] [PLOT WARNING] Not enough plots in arena "
+ getId() + "! Lacks " + (neededPlots - getPlotManager().getPlots().size()) + " plots");
getPlugin().getDebugger().sendConsoleMsg(
"&c[PLOT WARNING] Required " + neededPlots + " but have " + getPlotManager().getPlots().size());
getPlugin().getDebugger().sendConsoleMsg("&c[PLOT WARNING] Instance was stopped!");
getPlugin().getArenaManager().stopGame(true, this);
}
List<Player> players = new ArrayList<>(getPlayersLeft());
for (Plot plot : getPlotManager().getPlots()) {
if (players.isEmpty()) {
break;
}
if (!plot.getMembers().isEmpty()) {
continue;
}
if (!getPlugin().getUserManager().getUser(players.get(0)).isSpectator()) {
plot.addMember(players.remove(0), this, true);
}
}
for (Plot plot : getPlotManager().getPlots()) {
if (plot.getMembers().isEmpty()) {
continue;
}
for (Player member : plot.getMembers()) {
getPlotList().put(member, plot);
}
}
getPlotManager().teleportToPlots();
}
@Override
public boolean enoughPlayersToContinue() {
int size = getPlayersLeft().size();
if (size > plotMemberSize) {
return true;
}
if (size == plotMemberSize) {
return !new HashSet<>(getPlotManager().getPlot(getPlayersLeft().get(0)).getMembers())
.containsAll(getPlayersLeft());
}
return false;
}
public void setNextPlot() {
List<Plot> plots = new ArrayList<>(getPlotList().values());
plots.removeAll(playedPlots);
if (plots.isEmpty()) {
plots = new ArrayList<>(getPlotList().values());
playedPlots.clear();
}
Plot nextPlot = plots.get(getPlugin().getRandom().nextInt(plots.size()));
playedPlots.add(nextPlot);
buildPlot = nextPlot;
getPlugin().getDebugger().debug("Arena {0} Next BuilderTeam is {1}", getId(), nextPlot.getFormattedMembers());
teleportPlayersToPlot(nextPlot);
}
public void resetBuildPlot() {
if (buildPlot != null) {
buildPlot.resetPlot();
}
removedCharsAt.clear();
setBuildPlot(null);
setCurrentTheme(null);
whoGuessed.clear();
round += 1;
getPlayers().forEach(player -> getPlugin().getActionBarManager().clearActionBarsFromPlayer(player));
}
public void teleportPlayersToPlot(Plot plot) {
Location plotLoc = plot.getTeleportLocation();
for (Player player : getPlayers()) {
VersionUtils.teleport(player, plotLoc);
player.setPlayerWeather(plot.getWeatherType());
player.setPlayerTime(Plot.Time.format(plot.getTime(), player.getWorld().getTime()), false);
VersionUtils.setCollidable(player, false);
player.setGameMode(GameMode.ADVENTURE);
player.setAllowFlight(true);
player.setFlying(true);
player.getInventory().clear();
player.updateInventory();
}
}
@Override
public void setMinimumPlayers(int amount) {
if (amount <= plotMemberSize) {
getPlugin().getDebugger().debug(
"Minimum players amount for TEAM game mode arena cannot be less than 3! Setting amount to 3!");
setArenaOption("MINIMUM_PLAYERS", 3);
return;
}
super.setMinimumPlayers(amount);
}
public void addWhoGuessed(Player player) {
whoGuessed.add(player);
getPlugin().getRewardsHandler().performReward(player, this,
getPlugin().getRewardsHandler().getRewardType("GUESS"), -1);
int timer = getTimer();
// decrease game time by guessed theme
if (timer >= 15) {
setTimer(timer - getPlugin().getConfig().getInt("Time-Manager." + getArenaType().getPrefix() + ".Guess"));
}
// -1 because builder can´t guess
if (whoGuessed.size() >= getPlayersLeft().size() - 1) {
setTimer(getPlugin().getConfig().getInt("Time-Manager." + getArenaType().getPrefix() + ".Round-Delay"));
setArenaInGameState(ArenaInGameState.PLOT_VOTING);
new MessageBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESSED").asKey().arena(this).sendArena();
getPlugin().getRewardsHandler().performReward(this,
getPlugin().getRewardsHandler().getRewardType("GUESS_ALL"));
}
}
public void broadcastPlayerGuessed(Player player) {
int bonusAmount = getPlugin().getConfig().getInt("Guessing-Points." + (whoGuessed.size() + 1), 0);
int points = currentTheme.getDifficulty().getPointsReward() + bonusAmount;
getPlotManager().getPlot(player).addPoints(points);
buildPlot.addPoints(getPlugin().getConfig().getInt("Guessing-Points.Builder", 1));
new MessageBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESS_GUESSED").asKey().arena(this).player(player)
.sendArena();
new MessageBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESS_POINTS").asKey().integer(points).arena(this)
.player(player).sendPlayer();
addWhoGuessed(player);
Bukkit.getScheduler().runTask(getPlugin(),
() -> Bukkit.getPluginManager().callEvent(new PlayerThemeGuessEvent(this, currentTheme)));
}
public GuessTheme getCurrentBBTheme() {
return currentTheme;
}
public boolean isCurrentThemeSet() {
return currentTheme != null;
}
public List<Player> getCurrentBuilders() {
if (buildPlot == null) {
return new ArrayList<>();
}
return buildPlot.getMembers();
}
public Plot getBuildPlot() {
return buildPlot;
}
public void setBuildPlot(Plot buildPlot) {
this.buildPlot = buildPlot;
}
public List<String> getPlayedThemes() {
return playedThemes;
}
public int getRound() {
return round;
}
public void setCurrentTheme(GuessTheme currentTheme) {
if (currentTheme == null) {
getPlugin().getDebugger().debug("Arena {0} set Theme null", getId());
} else {
getPlugin().getDebugger().debug("Arena {0} set Theme to {1} ({2})", getId(),
currentTheme.getThemesAsString(), currentTheme.getDifficulty());
}
this.currentTheme = currentTheme;
}
public List<Player> getWhoGuessed() {
return whoGuessed;
}
public List<Integer> getRemovedCharsAt() {
return removedCharsAt;
}
}
@@ -1,460 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.impl;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.api.event.game.BBGameChangeStateEvent;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.managers.ScoreboardManager;
import plugily.projects.buildbattle.arena.managers.plots.PlotManager;
import plugily.projects.buildbattle.arena.options.ArenaOption;
import plugily.projects.buildbattle.menus.options.registry.particles.ParticleRefreshScheduler;
import plugily.projects.commonsbox.minecraft.compat.ServerVersion;
import plugily.projects.commonsbox.minecraft.compat.VersionUtils;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.commonsbox.string.StringFormatUtils;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
/**
* @author Plajer
* <p>
* Created at 18.01.2019
*/
public class BaseArena extends BukkitRunnable {
private final List<Player> players = new ArrayList<>();
private final List<Player> spectators = new ArrayList<>();
//instead of 2 (lobby, end) location fields we use map with GameLocation enum
private final Map<GameLocation, Location> gameLocations = new EnumMap<>(GameLocation.class);
//all arena values that are integers, contains constant and floating values
private final Map<ArenaOption, Integer> arenaOptions = new EnumMap<>(ArenaOption.class);
private final Main plugin;
private final String id;
private final PlotManager plotManager;
private final ScoreboardManager scoreboardManager;
private String mapName = "";
//todo move?
private String theme = "Theme";
private ArenaState arenaState;
private BossBar gameBar;
private ArenaType arenaType;
private int plotSize = 2;
private boolean forceStart = false;
private boolean ready = true;
protected ParticleRefreshScheduler particleRefreshSched;
public BaseArena(String id, Main plugin) {
arenaState = ArenaState.WAITING_FOR_PLAYERS;
this.plugin = plugin;
this.id = id == null ? "" : id;
if(ServerVersion.Version.isCurrentEqualOrHigher(ServerVersion.Version.v1_9_R1) && plugin.getConfigPreferences().getOption(ConfigPreferences.Option.BOSSBAR_ENABLED)) {
gameBar = Bukkit.createBossBar(plugin.getChatManager().colorMessage("Bossbar.Waiting-For-Players"), BarColor.BLUE, BarStyle.SOLID);
}
plotManager = new PlotManager(this);
scoreboardManager = new ScoreboardManager(this);
for(ArenaOption option : ArenaOption.values()) {
arenaOptions.put(option, option.getDefaultValue());
}
}
/**
* Checks if arena is validated and ready to play
*
* @return true = ready, false = not ready either you must validate it or it's wrongly created
*/
public boolean isReady() {
return ready;
}
public void setReady(boolean ready) {
this.ready = ready;
}
public PlotManager getPlotManager() {
return plotManager;
}
public ArenaType getArenaType() {
return arenaType;
}
public void setArenaType(ArenaType arenaType) {
this.arenaType = arenaType;
}
public void setPlotSize(int plotSize) {
this.plotSize = plotSize;
}
public int getPlotSize() {
return plotSize;
}
@Override
public void run() {
}
public void start() {
runTaskTimer(plugin, 20L, 20L);
}
/**
* Executes boss bar action for arena
*
* @param action add or remove a player from boss bar
* @param p player
*/
public void doBarAction(@NotNull BarAction action, Player p) {
if(p == null || gameBar == null || !ServerVersion.Version.isCurrentEqualOrHigher(ServerVersion.Version.v1_9_R1) || !plugin.getConfigPreferences().getOption(ConfigPreferences.Option.BOSSBAR_ENABLED)) {
return;
}
if(action == BarAction.ADD) {
gameBar.addPlayer(p);
} else if(action == BarAction.REMOVE) {
gameBar.removePlayer(p);
}
}
public void updateBossBar() {
}
public void distributePlots() {
}
public void sendBuildLeftTimeMessage() {
int timer = getTimer();
String message = plugin.getChatManager().colorMessage("In-Game.Messages.Time-Left-To-Build").replace("%FORMATTEDTIME%", StringFormatUtils.formatIntoMMSS(timer));
String subtitle = plugin.getChatManager().colorMessage("In-Game.Messages.Time-Left-Subtitle").replace("%FORMATTEDTIME%", Integer.toString(timer));
for(Player p : players) {
VersionUtils.sendActionBar(p, message);
p.sendMessage(plugin.getChatManager().getPrefix() + message);
VersionUtils.sendSubTitle(p, subtitle, 5, 30, 5);
}
}
public ScoreboardManager getScoreboardManager() {
return scoreboardManager;
}
public boolean isForceStart() {
return forceStart;
}
public void setForceStart(boolean forceStart) {
this.forceStart = forceStart;
}
/**
* Get arena ID, ID != map name
* ID is used to get and manage arenas
*
* @return arena ID
*/
@NotNull
public String getID() {
return id;
}
/**
* Lobby location of arena
*
* @return lobby loc of arena
*/
@Nullable
public Location getLobbyLocation() {
return gameLocations.get(BaseArena.GameLocation.LOBBY);
}
public void setLobbyLocation(Location loc) {
gameLocations.put(BaseArena.GameLocation.LOBBY, loc);
}
/**
* Min players that are required to start arena
*
* @return min players size
*/
public int getMinimumPlayers() {
return getOption(ArenaOption.MINIMUM_PLAYERS);
}
public void setMinimumPlayers(int amount) {
setOptionValue(ArenaOption.MINIMUM_PLAYERS, amount);
}
/**
* Get map name, map name != ID
* Map name is used in signs
*
* @return map name String
*/
@NotNull
public String getMapName() {
return mapName;
}
public void setMapName(String mapname) {
if(mapname != null)
this.mapName = mapname;
}
public void addPlayer(Player player) {
players.add(player);
}
public void removePlayer(Player player) {
players.remove(player);
}
public void clearPlayers() {
players.clear();
}
public void addSpectator(Player player) {
spectators.add(player);
}
public void removeSpectator(Player player) {
spectators.remove(player);
}
/**
* Global timer of arena
*
* @return timer of arena
*/
public int getTimer() {
return getOption(ArenaOption.TIMER);
}
public void setTimer(int timer) {
setOptionValue(ArenaOption.TIMER, timer);
}
/**
* Max players size arena can hold
*
* @return max players size
*/
public int getMaximumPlayers() {
return getOption(ArenaOption.MAXIMUM_PLAYERS);
}
public void setMaximumPlayers(int amount) {
setOptionValue(ArenaOption.MAXIMUM_PLAYERS, amount);
}
/**
* Arena state of arena
*
* @return arena state
* @see ArenaState
*/
@NotNull
public ArenaState getArenaState() {
return arenaState;
}
/**
* Changes arena state of arena
* Calls BBGameChangeStateEvent
*
* @param arenaState arena state to change
* @see BBGameChangeStateEvent
*/
public void setArenaState(@NotNull ArenaState arenaState) {
if(this.arenaState != null) {
plugin.getServer().getPluginManager().callEvent(new BBGameChangeStateEvent(arenaState, this, this.arenaState));
}
this.arenaState = arenaState;
plugin.getSignManager().updateSigns();
}
/**
* Get players in game
*
* @return List with players
*/
@NotNull
public List<Player> getPlayers() {
return players;
}
/**
* Get players of the game and spectators
*
* @return List with players
*/
@NotNull
public List<Player> getAllArenaPlayers() {
List<Player> allPlayers = new ArrayList<>(players);
allPlayers.addAll(spectators);
return allPlayers;
}
public List<Player> getSpectators() {
return spectators;
}
public Main getPlugin() {
return plugin;
}
public void teleportAllToEndLocation() {
if(plugin.getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED) && ConfigUtils.getConfig(plugin, "bungee").getBoolean("End-Location-Hub", true)) {
players.forEach(plugin.getBungeeManager()::connectToHub);
spectators.forEach(plugin.getBungeeManager()::connectToHub);
return;
}
Location location = getEndLocation();
if(location == null) {
location = getLobbyLocation();
System.out.print("EndLocation for arena " + getID() + " isn't intialized!");
}
if(location != null) {
for(Player player : players) {
player.teleport(location);
}
for(Player player : spectators) {
player.teleport(location);
}
}
}
public void teleportToLobby(Player player) {
Location location = getLobbyLocation();
if(location == null) {
System.out.print("LobbyLocation isn't intialized for arena " + getID());
return;
}
player.teleport(location);
}
public void teleportToEndLocation(Player player) {
if(plugin.getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED) && ConfigUtils.getConfig(plugin, "bungee").getBoolean("End-Location-Hub", true)) {
plugin.getBungeeManager().connectToHub(player);
return;
}
Location location = getEndLocation();
if(location == null) {
location = getLobbyLocation();
System.out.print("EndLocation for arena " + getID() + " isn't intialized!");
}
if(location != null) {
player.teleport(location);
}
}
public void giveRewards() {
}
/**
* Get current arena theme
*
* @return arena theme String or "Theme" as default
*/
@NotNull
public String getTheme() {
//make sure to have no NPE
return theme == null ? "Theme" : theme;
}
public void setTheme(String theme) {
this.theme = theme == null ? "Theme" : theme;
}
/**
* End location of arena
*
* @return end loc of arena
*/
@Nullable
public Location getEndLocation() {
return gameLocations.get(GameLocation.END);
}
public void setEndLocation(Location endLoc) {
gameLocations.put(GameLocation.END, endLoc);
}
protected BossBar getGameBar() {
return gameBar;
}
public int getOption(ArenaOption option) {
return arenaOptions.getOrDefault(option, 0);
}
public void setOptionValue(ArenaOption option, int value) {
arenaOptions.put(option, value);
}
public void addOptionValue(ArenaOption option, int value) {
arenaOptions.put(option, getOption(option) + value);
}
public enum ArenaType {
SOLO("Classic"), TEAM("Teams"), GUESS_THE_BUILD("Guess-The-Build");
private final String prefix;
ArenaType(String prefix) {
this.prefix = prefix;
}
public String getPrefix() {
return prefix;
}
}
public enum GameLocation {
LOBBY, END
}
public enum BarAction {
ADD, REMOVE
}
}
@@ -1,604 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.impl;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.api.StatsStorage;
import plugily.projects.buildbattle.api.event.game.BBGameEndEvent;
import plugily.projects.buildbattle.api.event.game.BBGameStartEvent;
import plugily.projects.buildbattle.arena.ArenaManager;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.managers.GuessTheBuildScoreboardManager;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.arena.options.ArenaOption;
import plugily.projects.buildbattle.handlers.reward.Reward;
import plugily.projects.buildbattle.menus.options.registry.particles.ParticleRefreshScheduler;
import plugily.projects.buildbattle.menus.themevoter.BBTheme;
import plugily.projects.buildbattle.user.User;
import plugily.projects.buildbattle.utils.Debugger;
import plugily.projects.buildbattle.utils.MessageUtils;
import plugily.projects.commonsbox.minecraft.compat.VersionUtils;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.commonsbox.minecraft.item.ItemBuilder;
import plugily.projects.commonsbox.minecraft.misc.MiscUtils;
import plugily.projects.commonsbox.minecraft.misc.stuff.ComplementAccessor;
import plugily.projects.commonsbox.minecraft.serialization.InventorySerializer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class GuessTheBuildArena extends BaseArena {
private final List<Player> whoGuessed = new ArrayList<>();
private final GuessTheBuildScoreboardManager scoreboardManager;
private int round = 1;
private BBTheme currentTheme;
private boolean themeSet;
private boolean nextRoundCooldown = false;
private Player currentBuilder;
private Map<Player, Integer> playersPoints = new HashMap<>();
private List<Integer> removedCharsAt = new ArrayList<>();
public GuessTheBuildArena(String id, Main plugin) {
super(id, plugin);
scoreboardManager = new GuessTheBuildScoreboardManager(this);
}
@Override
public void run() {
//idle task
if(getArenaState() == ArenaState.WAITING_FOR_PLAYERS && getPlayers().isEmpty()) {
return;
}
updateBossBar();
switch(getArenaState()) {
case WAITING_FOR_PLAYERS:
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
getPlugin().getServer().setWhitelist(false);
}
getPlotManager().resetPlotsGradually();
int minPlayers = getMinimumPlayers();
if(getPlayers().size() < minPlayers) {
if(getTimer() <= 0) {
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.LOBBY, this));
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Messages.Lobby-Messages.Waiting-For-Players").replace("%MINPLAYERS%", Integer.toString(minPlayers)));
return;
}
} else {
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Messages.Lobby-Messages.Enough-Players-To-Start"));
setArenaState(ArenaState.STARTING);
Bukkit.getPluginManager().callEvent(new BBGameStartEvent(this));
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.LOBBY, this));
}
setTimer(getTimer() - 1);
break;
case STARTING:
int timer = getTimer();
int lobbyTimer = getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.LOBBY, this);
float exp = (float) (timer / (double) lobbyTimer);
if(exp > 1f || exp < 0f) {
exp = 1f;
}
for(Player player : getPlayers()) {
player.setExp(exp);
player.setLevel(timer);
}
int minPls = getMinimumPlayers();
if(getPlayers().size() < minPls) {
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Messages.Lobby-Messages.Waiting-For-Players").replace("%MINPLAYERS%", Integer.toString(minPls)));
setArenaState(ArenaState.WAITING_FOR_PLAYERS);
Bukkit.getPluginManager().callEvent(new BBGameStartEvent(this));
setTimer(lobbyTimer);
for(Player player : getPlayers()) {
player.setExp(1);
player.setLevel(0);
}
break;
}
if(getTimer() == 0) {
particleRefreshSched = new ParticleRefreshScheduler(getPlugin());
if(!getPlotManager().isPlotsCleared()) {
getPlotManager().resetQueuedPlots();
}
setArenaState(ArenaState.IN_GAME);
for(Player player : getPlayers()) {
playersPoints.put(player, 0);
}
distributePlots();
getPlotManager().teleportToPlots();
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.DELAYED_TASK, this));
for(Player player : getPlayers()) {
player.getInventory().clear();
//to prevent world switch bug
Bukkit.getScheduler().runTaskLater(getPlugin(), () -> {
player.setGameMode(GameMode.ADVENTURE);
VersionUtils.setCollidable(player, false);
player.setAllowFlight(true);
player.setFlying(true);
}, 20);
}
Plot plot = getPlotManager().getPlot(getPlayers().get(round - 1));
org.bukkit.Location plotLoc = plot == null ? null : plot.getTeleportLocation();
if(plotLoc != null) {
for(Player p : getPlayers()) {
p.teleport(plotLoc);
getPlugin().getRewardsHandler().performReward(p, Reward.RewardType.START_GAME, -1);
}
}
nextRoundCooldown = true;
Bukkit.getScheduler().runTaskLater(getPlugin(), () -> nextRoundCooldown = false, 20L * getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.DELAYED_TASK, this));
if(plot != null) {
Bukkit.getScheduler().runTaskLater(getPlugin(), () -> plot.getMembers().forEach(player -> player.setGameMode(GameMode.CREATIVE)), 20);
}
break;
}
setTimer(getTimer() - 1);
break;
case IN_GAME:
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
getPlugin().getServer().setWhitelist(getMaximumPlayers() <= getPlayers().size());
}
if(currentBuilder == null && !nextRoundCooldown) {
currentBuilder = getPlayers().get(round - 1);
openThemeSelectionInventoryToCurrentBuilder();
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.THEME_SELECTION, this));
break;
}
if(!themeSet && getTimer() <= 0 && currentBuilder != null) {
Random r = new Random();
String type = "EASY";
switch(r.nextInt(2 + 1)) {
case 1:
type = "MEDIUM";
break;
case 2:
type = "HARD";
break;
default:
break;
}
List<String> themes = getPlugin().getConfigPreferences().getThemes(BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix() + "_" + type);
if(!themes.isEmpty()) {
BBTheme theme = new BBTheme(themes.get(themes.size() == 1 ? 0 : r.nextInt(themes.size())), BBTheme.Difficulty.valueOf(type));
setCurrentTheme(theme);
setThemeSet(true);
VersionUtils.sendActionBar(currentBuilder, getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Theme-Is-Name")
.replace("%THEME%", theme.getTheme()));
}
currentBuilder.closeInventory();
String roundMessage = getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Current-Round")
.replace("%ROUND%", Integer.toString(round))
.replace("%MAXPLAYERS%", Integer.toString(getPlayers().size()));
for(Player p : getPlayers()) {
VersionUtils.sendTitle(p, getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Start-Guessing-Title"), 5, 25, 5);
p.sendMessage(roundMessage);
}
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.BUILD, this));
break;
}
if(getTimer() <= 90 && currentTheme != null) {
if(getTimer() == 90) {
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Theme-Is-Long")
.replace("%NUM%", Integer.toString(currentTheme.getTheme().length())));
}
for(Player player : getPlayers()) {
if(currentBuilder == player) {
continue;
}
if(whoGuessed.contains(player)) {
VersionUtils.sendActionBar(player, currentTheme.getTheme());
}
StringBuilder actionbar = new StringBuilder();
List<Integer> charsAt = new ArrayList<>();
for(int i = 0; i < currentTheme.getTheme().length(); i++) {
if(!removedCharsAt.contains(i)) {
charsAt.add(i);
}
}
if(currentTheme.getTheme().length() - removedCharsAt.size() > 2) {
int t = getTimer();
if(t % 10 == 0 && t <= 70) {
int removeCharAt = charsAt.get(charsAt.size() == 1 ? 0 : new Random().nextInt(charsAt.size()));
removedCharsAt.add(removeCharAt);
continue;
}
}
for(int i = 0; i < currentTheme.getTheme().length(); i++) {
if(Character.isWhitespace(currentTheme.getTheme().charAt(i))) {
actionbar.append(" ");
continue;
}
if(removedCharsAt.contains(i)) {
actionbar.append(currentTheme.getTheme().charAt(i)).append(' ');
continue;
}
actionbar.append("_ ");
}
VersionUtils.sendActionBar(player, actionbar.toString());
}
}
if(getTimer() <= 0 && themeSet) {
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Theme-Was-Name").replace("%THEME%", currentTheme.getTheme()));
String themeTitle = getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Theme-Was-Title");
String themeSubtitle = getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Theme-Was-Subtitle")
.replace("%THEME%", currentTheme.getTheme());
for(Player p : getPlayers()) {
VersionUtils.sendTitles(p, themeTitle, themeSubtitle, 5, 25, 5);
}
removedCharsAt.clear();
currentBuilder = null;
setThemeSet(false);
setCurrentTheme(null);
whoGuessed.clear();
round++;
if(round > getPlayers().size()) {
setTimer(15);
setArenaState(ArenaState.ENDING);
Bukkit.getPluginManager().callEvent(new BBGameEndEvent(this));
break;
}
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.DELAYED_TASK, this));
nextRoundCooldown = true;
Bukkit.getScheduler().runTaskLater(getPlugin(), () -> {
nextRoundCooldown = false;
currentBuilder = getPlayers().get(round - 1);
Plot plot = getPlotManager().getPlot(currentBuilder);
org.bukkit.Location plotLoc = plot == null ? null : plot.getTeleportLocation();
for(Player p : getPlayers()) {
if(plot != null) {
if(plotLoc != null) {
p.teleport(plotLoc);
}
p.setPlayerWeather(plot.getWeatherType());
p.setPlayerTime(Plot.Time.format(plot.getTime(), p.getWorld().getTime()), false);
}
VersionUtils.setCollidable(p, false);
p.setGameMode(GameMode.ADVENTURE);
p.setAllowFlight(true);
p.setFlying(true);
p.getInventory().clear(8);
p.updateInventory();
}
openThemeSelectionInventoryToCurrentBuilder();
if(plot != null) {
plot.getMembers().forEach(player -> player.setGameMode(GameMode.CREATIVE));
}
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.THEME_SELECTION, this));
if(getArenaState() != ArenaState.IN_GAME || themeSet) {
return;
}
for(Player player : getPlayers()) {
if(currentBuilder != player) {
VersionUtils.sendSubTitle(player, getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Theme-Being-Selected"), 5, 25, 5);
}
}
}, 20L * getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.DELAYED_TASK, this));
//todo next round info and game state?
break;
}
if(getPlayers().size() < 2) {
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Messages.Game-End-Messages.Only-You-Playing"));
setArenaState(ArenaState.ENDING);
Bukkit.getPluginManager().callEvent(new BBGameEndEvent(this));
setTimer(15);
}
if(themeSet && (getTimer() == (4 * 60) || getTimer() == (3 * 60) || getTimer() == 5 * 60 || getTimer() == 30 || getTimer() == 2 * 60 || getTimer() == 60 || getTimer() == 15)) {
sendBuildLeftTimeMessage();
}
//if player leaves during round force next round
if(currentBuilder != null && !currentBuilder.isOnline()) {
setTimer(1);
}
if(getTimer() != 0 && currentBuilder != null) {
if(getOption(ArenaOption.IN_PLOT_CHECKER) == 1) {
setOptionValue(ArenaOption.IN_PLOT_CHECKER, 0);
Plot buildPlot = getPlugin().getUserManager().getUser(currentBuilder).getCurrentPlot();
if(buildPlot != null) {
org.bukkit.Location plotLoc = buildPlot.getTeleportLocation();
for(Player player : getPlayers()) {
player.setPlayerWeather(buildPlot.getWeatherType());
player.setPlayerTime(Plot.Time.format(buildPlot.getTime(), player.getWorld().getTime()), false);
if(plotLoc != null && !buildPlot.getCuboid().isInWithMarge(player.getLocation(), 5)) {
player.teleport(plotLoc);
player.sendMessage(getPlugin().getChatManager().getPrefix() + getPlugin().getChatManager().colorMessage("In-Game.Messages.Cant-Fly-Outside-Plot"));
}
}
}
}
addOptionValue(ArenaOption.IN_PLOT_CHECKER, 1);
}
setTimer(getTimer() - 1);
break;
case ENDING:
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
getPlugin().getServer().setWhitelist(false);
}
if(getPlugin().getConfig().getBoolean("Firework-When-Game-Ends", true)) {
for(Player player : getPlayers()) {
MiscUtils.spawnRandomFirework(player.getLocation());
}
}
if(getTimer() <= 0) {
scoreboardManager.stopAllScoreboards();
for(Player player : getAllArenaPlayers()) {
teleportToEndLocation(player);
if(getGameBar() != null) {
getGameBar().removePlayer(player);
}
User user = getPlugin().getUserManager().getUser(player);
user.removeScoreboard(this);
user.setSpectator(false);
player.getInventory().clear();
player.setGameMode(GameMode.SURVIVAL);
player.setFlying(false);
player.setAllowFlight(false);
player.getInventory().setArmorContents(null);
player.sendMessage(getPlugin().getChatManager().getPrefix() + getPlugin().getChatManager().colorMessage("Commands.Teleported-To-The-Lobby"));
user.addStat(StatsStorage.StatisticType.GAMES_PLAYED, 1);
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.INVENTORY_MANAGER_ENABLED)) {
InventorySerializer.loadInventory(getPlugin(), player);
}
//fast solution
Plot plot = getPlotManager().getPlot(player);
if(plot != null)
plot.fullyResetPlot();
}
// do it in the main thread to prevent async catch from bukkit
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), this::giveRewards);
clearPlayers();
if(particleRefreshSched != null) {
particleRefreshSched.task.cancel();
}
setArenaState(ArenaState.RESTARTING);
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
getPlugin().getServer().getOnlinePlayers().forEach(this::addPlayer);
}
}
setTimer(getTimer() - 1);
break;
case RESTARTING:
setOptionValue(ArenaOption.IN_PLOT_CHECKER, 0);
whoGuessed.clear();
playersPoints.clear();
round = 1;
clearPlayers();
nextRoundCooldown = false;
setTimer(14);
setArenaState(ArenaState.WAITING_FOR_PLAYERS);
currentBuilder = null;
setThemeSet(false);
setCurrentTheme(null);
for(Player spectator : new ArrayList<>(getSpectators())) {
ArenaManager.leaveAttempt(spectator, this);
}
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
if(ConfigUtils.getConfig(getPlugin(), "bungee").getBoolean("Shutdown-When-Game-Ends")) {
getPlugin().getServer().shutdown();
}
ArenaRegistry.shuffleBungeeArena();
for(Player player : Bukkit.getOnlinePlayers()) {
ArenaManager.joinAttempt(player, ArenaRegistry.getArenas().get(ArenaRegistry.getBungeeArena()));
}
}
break;
}
}
private void openThemeSelectionInventoryToCurrentBuilder() {
if(currentBuilder == null)
return;
Random r = new Random();
List<String> themes = getPlugin().getConfigPreferences().getThemes(BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix() + "_EASY");
String itemLore = getPlugin().getChatManager().colorMessage("Menus.Guess-The-Build-Theme-Selector.Theme-Item-Lore");
String themeItemName = getPlugin().getChatManager().colorMessage("Menus.Guess-The-Build-Theme-Selector.Theme-Item-Name");
Inventory inv = ComplementAccessor.getComplement().createInventory(null, 27, getPlugin().getChatManager().colorMessage("Menus.Guess-The-Build-Theme-Selector.Inventory-Name"));
inv.setItem(11, new ItemBuilder(Material.PAPER).name(themeItemName
.replace("%theme%", !themes.isEmpty() ? themes.get(themes.size() == 1 ? 0 : r.nextInt(themes.size())) : ""))
.lore(itemLore
.replace("%difficulty%", getPlugin().getChatManager().colorMessage("Menus.Guess-The-Build-Theme-Selector.Difficulties.Easy"))
.replace("%points%", "1").split(";")).build());
themes = getPlugin().getConfigPreferences().getThemes(BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix() + "_MEDIUM");
inv.setItem(13, new ItemBuilder(Material.PAPER).name(themeItemName
.replace("%theme%", !themes.isEmpty() ? themes.get(themes.size() == 1 ? 0 : r.nextInt(themes.size())) : ""))
.lore(itemLore
.replace("%difficulty%", getPlugin().getChatManager().colorMessage("Menus.Guess-The-Build-Theme-Selector.Difficulties.Medium"))
.replace("%points%", "2").split(";")).build());
themes = getPlugin().getConfigPreferences().getThemes(BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix() + "_HARD");
inv.setItem(15, new ItemBuilder(Material.PAPER).name(themeItemName
.replace("%theme%", !themes.isEmpty() ? themes.get(themes.size() == 1 ? 0 : r.nextInt(themes.size())) : ""))
.lore(itemLore
.replace("%difficulty%", getPlugin().getChatManager().colorMessage("Menus.Guess-The-Build-Theme-Selector.Difficulties.Hard"))
.replace("%points%", "3").split(";")).build());
currentBuilder.openInventory(inv);
currentBuilder.getInventory().setItem(8, getPlugin().getOptionsRegistry().getMenuItem());
currentBuilder.updateInventory();
}
public void recalculateLeaderboard() {
playersPoints = playersPoints.entrySet()
.stream()
.sorted((Map.Entry.<Player, Integer>comparingByValue().reversed()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
}
@Override
public void giveRewards() {
List<Player> list = new ArrayList<>(playersPoints.keySet());
int size = list.size();
for(int i = 0; i <= size; i++) {
if(size - 1 < i) {
continue;
}
getPlugin().getRewardsHandler().performReward(list.get(i), Reward.RewardType.PLACE, i + 1);
}
getPlugin().getRewardsHandler().performReward(this, Reward.RewardType.END_GAME);
}
@Override
public void updateBossBar() {
if(getGameBar() == null) {
return;
}
switch(getArenaState()) {
case WAITING_FOR_PLAYERS:
getGameBar().setTitle(getPlugin().getChatManager().colorMessage("Bossbar.Waiting-For-Players"));
break;
case STARTING:
getGameBar().setTitle(getPlugin().getChatManager().colorMessage("Bossbar.Starting-In").replace("%time%", Integer.toString(getTimer())));
break;
case IN_GAME:
getGameBar().setTitle(getPlugin().getChatManager().colorMessage("Bossbar.Time-Left").replace("%time%", Integer.toString(getTimer())));
break;
default:
break;
}
}
@Override
public void distributePlots() {
//clear plots before distribution to avoid problems
for(Plot plot : getPlotManager().getPlots()) {
plot.getMembers().clear();
}
List<Player> players = new ArrayList<>(getPlayers());
for(Plot plot : getPlotManager().getPlots()) {
if(players.isEmpty()) {
break;
}
Player first = players.get(0);
plot.addMember(first, this, true);
getPlugin().getUserManager().getUser(first).setCurrentPlot(plot);
players.remove(0);
}
if(!players.isEmpty()) {
MessageUtils.errorOccurred();
Debugger.sendConsoleMsg("&c[Build Battle] [PLOT WARNING] Not enough plots in arena " + getID() + "!");
Debugger.sendConsoleMsg("&c[PLOT WARNING] Required " + getPlayers().size() + " but have " + getPlotManager().getPlots().size());
Debugger.sendConsoleMsg("&c[PLOT WARNING] Instance was stopped!");
ArenaManager.stopGame(false, this);
}
}
public int getRound() {
return round;
}
@Nullable
public Player getCurrentBuilder() {
return currentBuilder;
}
public BBTheme getCurrentTheme() {
return currentTheme;
}
public void setCurrentTheme(BBTheme currentTheme) {
this.currentTheme = currentTheme;
}
@NotNull
public List<Player> getWhoGuessed() {
return whoGuessed;
}
public void addWhoGuessed(Player player) {
whoGuessed.add(player);
getPlugin().getRewardsHandler().performReward(player, Reward.RewardType.GTB_GUESS, -1);
//decrease game time by guessed theme
if(getTimer() >= 15) {
setTimer(getTimer() - getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.TIME_SHORTENER, this));
}
//-1 because builder can´t guess
if(whoGuessed.size() >= getPlayers().size() - 1) {
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.ALL_GUESSED, this));
for(Player players : getPlayers()) {
players.sendMessage(getPlugin().getChatManager().getPrefix() + getPlugin().getChatManager().colorMessage("In-Game.Guess-The-Build.Theme-Guessed"));
getPlugin().getRewardsHandler().performReward(players, Reward.RewardType.GTB_ALL_GUESSED, -1);
}
}
}
@Override
public GuessTheBuildScoreboardManager getScoreboardManager() {
return scoreboardManager;
}
public boolean isThemeSet() {
return themeSet;
}
public void setThemeSet(boolean themeSet) {
this.themeSet = themeSet;
}
public Map<Player, Integer> getPlayersPoints() {
return playersPoints;
}
}
@@ -1,703 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.impl;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.api.StatsStorage;
import plugily.projects.buildbattle.api.event.game.BBGameEndEvent;
import plugily.projects.buildbattle.api.event.game.BBGameStartEvent;
import plugily.projects.buildbattle.arena.ArenaManager;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.arena.options.ArenaOption;
import plugily.projects.buildbattle.handlers.HolidayManager;
import plugily.projects.buildbattle.handlers.language.LanguageManager;
import plugily.projects.buildbattle.handlers.reward.Reward;
import plugily.projects.buildbattle.menus.options.registry.particles.ParticleRefreshScheduler;
import plugily.projects.buildbattle.menus.themevoter.VoteMenu;
import plugily.projects.buildbattle.menus.themevoter.VotePoll;
import plugily.projects.buildbattle.user.User;
import plugily.projects.buildbattle.utils.Debugger;
import plugily.projects.buildbattle.utils.MessageUtils;
import plugily.projects.commonsbox.minecraft.compat.VersionUtils;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.commonsbox.minecraft.misc.MiscUtils;
import plugily.projects.commonsbox.minecraft.serialization.InventorySerializer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.logging.Level;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class SoloArena extends BaseArena {
private final Main plugin;
private final Map<Integer, List<Player>> topList = new HashMap<>();
private final Queue<Plot> queue = new LinkedList<>();
private boolean receivedVoteItems;
private Plot votingPlot;
private boolean voteTime;
private boolean themeVoteTime = true;
private boolean themeTimerSet = false;
private VoteMenu voteMenu;
public SoloArena(String id, Main plugin) {
super(id, plugin);
this.plugin = plugin;
}
/**
* Initiates voting poll
*/
public void initPoll() {
voteMenu = new VoteMenu(this);
voteMenu.resetPoll();
}
public VotePoll getVotePoll() {
return voteMenu.getVotePoll();
}
public VoteMenu getVoteMenu() {
return voteMenu;
}
/**
* Is voting time in game?
*
* @return true = voting time, false = no
*/
public boolean isVoting() {
return voteTime;
}
public void setVoting(boolean voting) {
voteTime = voting;
}
@NotNull
public Queue<Plot> getQueue() {
return queue;
}
@Override
public void run() {
//idle task
if(getArenaState() == ArenaState.WAITING_FOR_PLAYERS && getPlayers().isEmpty()) {
return;
}
updateBossBar();
switch(getArenaState()) {
case WAITING_FOR_PLAYERS:
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
getPlugin().getServer().setWhitelist(false);
}
getPlotManager().resetPlotsGradually();
int minmPlayers = getMinimumPlayers();
if(getPlayers().size() < minmPlayers) {
if(getTimer() <= 0) {
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.LOBBY, this));
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Messages.Lobby-Messages.Waiting-For-Players").replace("%MINPLAYERS%", Integer.toString(minmPlayers)));
return;
}
} else {
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Messages.Lobby-Messages.Enough-Players-To-Start"));
setArenaState(ArenaState.STARTING);
if(HolidayManager.getCurrentHoliday() != HolidayManager.HolidayType.NONE) {
initPoll();
}
Bukkit.getPluginManager().callEvent(new BBGameStartEvent(this));
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.LOBBY, this));
}
setTimer(getTimer() - 1);
break;
case STARTING:
int lobbyTimer = getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.LOBBY, this);
int timer = getTimer();
float exp = (float) (timer / (double) lobbyTimer);
if(exp > 1f || exp < 0f) {
exp = 1f;
}
for(Player player : getPlayers()) {
player.setExp(exp);
player.setLevel(timer);
}
int minPlayers = getMinimumPlayers();
if(getPlayers().size() < minPlayers && !isForceStart()) {
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Messages.Lobby-Messages.Waiting-For-Players").replace("%MINPLAYERS%", Integer.toString(minPlayers)));
setArenaState(ArenaState.WAITING_FOR_PLAYERS);
Bukkit.getPluginManager().callEvent(new BBGameStartEvent(this));
setTimer(lobbyTimer);
for(Player player : getPlayers()) {
player.setExp(1);
player.setLevel(0);
}
break;
}
if(getTimer() == 0 || isForceStart()) {
particleRefreshSched = new ParticleRefreshScheduler(getPlugin());
if(!getPlotManager().isPlotsCleared()) {
getPlotManager().resetQueuedPlots();
}
setArenaState(ArenaState.IN_GAME);
distributePlots();
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.THEME_VOTE, this));
for(Player player : getPlayers()) {
player.getInventory().clear();
player.setGameMode(GameMode.CREATIVE);
player.setAllowFlight(true);
player.setFlying(true);
player.getInventory().setItem(8, getPlugin().getOptionsRegistry().getMenuItem());
//to prevent Multiverse changing gamemode bug
Bukkit.getScheduler().runTaskLater(getPlugin(), () -> player.setGameMode(GameMode.CREATIVE), 40);
getPlugin().getRewardsHandler().performReward(player, Reward.RewardType.START_GAME, -1);
}
}
if(isForceStart()) {
setForceStart(false);
}
setTimer(getTimer() - 1);
break;
case IN_GAME:
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
getPlugin().getServer().setWhitelist(getMaximumPlayers() <= getPlayers().size());
}
if(themeVoteTime) {
if(!themeTimerSet) {
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.THEME_VOTE, this));
setThemeTimerSet(true);
for(Player p : getPlayers()) {
p.openInventory(voteMenu.getInventory());
}
}
getPlayers().forEach(voteMenu::updateInventory);
if(getTimer() == 0) {
setThemeVoteTime(false);
if(getVotePoll() != null) {
setTheme(getVotePoll().getVotedTheme());
}
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.BUILD, this));
String message = getPlugin().getChatManager().colorMessage("In-Game.Messages.Lobby-Messages.Game-Started");
for(Player p : getPlayers()) {
p.closeInventory();
Plot plot = getPlotManager().getPlot(p);
if(plot != null) {
p.teleport(plot.getTeleportLocation());
}
p.sendMessage(getPlugin().getChatManager().getPrefix() + message);
}
} else {
setTimer(getTimer() - 1);
}
break;
}
if(!enoughPlayersToContinue()) {
getPlugin().getChatManager().broadcast(this, getPlugin().getChatManager().colorMessage("In-Game.Messages.Game-End-Messages.Only-You-Playing"));
setArenaState(ArenaState.ENDING);
Bukkit.getPluginManager().callEvent(new BBGameEndEvent(this));
setTimer(10);
}
int timerco = getTimer();
if((timerco == (4 * 60) || timerco == (3 * 60) || timerco == (5 * 60) || timerco == 30 || timerco == (2 * 60) || timerco == 60 || timerco == 15) && !voteTime) {
sendBuildLeftTimeMessage();
}
if(timerco != 0 && !receivedVoteItems) {
if(getOption(ArenaOption.IN_PLOT_CHECKER) == 1) {
setOptionValue(ArenaOption.IN_PLOT_CHECKER, 0);
for(Player player : getPlayers()) {
User user = getPlugin().getUserManager().getUser(player);
Plot buildPlot = user.getCurrentPlot();
if(buildPlot != null && buildPlot.getCuboid() != null && !buildPlot.getCuboid().isInWithMarge(player.getLocation(), 5)) {
player.teleport(buildPlot.getTeleportLocation());
player.sendMessage(getPlugin().getChatManager().getPrefix() + getPlugin().getChatManager().colorMessage("In-Game.Messages.Cant-Fly-Outside-Plot"));
}
}
}
addOptionValue(ArenaOption.IN_PLOT_CHECKER, 1);
} else if(timerco == 0 && !receivedVoteItems) {
for(Player player : getPlayers()) {
User user = getPlugin().getUserManager().getUser(player);
if(user.isSpectator()) continue;
if(!queue.contains(user.getCurrentPlot())) {
queue.add(user.getCurrentPlot());
}
player.getInventory().clear();
getPlugin().getVoteItems().giveVoteItems(player);
user.setStat(StatsStorage.StatisticType.LOCAL_POINTS, 3);
}
receivedVoteItems = true;
}
if(getTimer() == 0 && receivedVoteItems) {
setVoting(true);
if(!queue.isEmpty()) {
voteForNextPlot();
} else {
if(votingPlot != null) {
if(votingPlot.getPoints() == 0) {
String message = getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Voted-For-Player-Plot").replace("%PLAYER%", votingPlot.getFormattedMembers());
for(Player player : getPlayers()) {
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.ANNOUNCE_PLOTOWNER_LATER)) {
for(Player p : getPlayers()) {
String owner = getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Plot-Owner-Title");
owner = formatWinners(votingPlot, owner);
VersionUtils.sendTitle(p, owner, 5, 40, 5);
p.sendMessage(getPlugin().getChatManager().getPrefix() + message);
}
}
User user = getPlugin().getUserManager().getUser(player);
int points = user.getStat(StatsStorage.StatisticType.LOCAL_POINTS);
//no vote made, in this case make it a good vote
if(points == 0) {
points = 3;
}
if(!votingPlot.getMembers().contains(player))
votingPlot.setPoints(votingPlot.getPoints() + points);
user.setStat(StatsStorage.StatisticType.LOCAL_POINTS, 3);
}
}
}
calculateResults();
Plot winnerPlot = null;
for(List<Player> potentialWinners : topList.values()) {
if(!potentialWinners.isEmpty()) {
winnerPlot = getPlotManager().getPlot(potentialWinners.get(0));
break;
}
}
if(winnerPlot == null) {
getPlugin().getLogger().log(Level.SEVERE, "Fatal error in getting winner plot in game! No plot contain any online player!");
setArenaState(ArenaState.ENDING);
Bukkit.getPluginManager().callEvent(new BBGameEndEvent(this));
setTimer(10);
break;
}
announceResults();
Location winnerLocation = winnerPlot.getTeleportLocation();
for(Player player : getAllArenaPlayers()) {
player.teleport(winnerLocation);
String winner = getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Winner-Title");
winner = formatWinners(winnerPlot, winner);
VersionUtils.sendTitle(player, winner, 5, 35, 5);
}
setArenaState(ArenaState.ENDING);
Bukkit.getPluginManager().callEvent(new BBGameEndEvent(this));
setTimer(10);
}
}
setTimer(getTimer() - 1);
break;
case ENDING:
getScoreboardManager().stopAllScoreboards();
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
getPlugin().getServer().setWhitelist(false);
}
setVoting(false);
setThemeTimerSet(false);
if(getPlugin().getConfig().getBoolean("Firework-When-Game-Ends", true)) {
for(Player player : getAllArenaPlayers()) {
MiscUtils.spawnRandomFirework(player.getLocation());
}
}
if(getTimer() <= 0) {
for(Player player : getAllArenaPlayers()) {
User user = plugin.getUserManager().getUser(player);
user.removeScoreboard(this);
user.setSpectator(false);
teleportToEndLocation(player);
doBarAction(BarAction.REMOVE, player);
player.getInventory().clear();
player.setGameMode(GameMode.SURVIVAL);
player.setFlying(false);
player.setAllowFlight(false);
player.getInventory().setArmorContents(null);
player.sendMessage(getPlugin().getChatManager().getPrefix() + getPlugin().getChatManager().colorMessage("Commands.Teleported-To-The-Lobby"));
user.addStat(StatsStorage.StatisticType.GAMES_PLAYED, 1);
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.INVENTORY_MANAGER_ENABLED)) {
InventorySerializer.loadInventory(getPlugin(), player);
}
//plot might be already deleted by team mate in TEAM game mode
Plot plot = getPlotManager().getPlot(player);
if(plot != null) {
plot.fullyResetPlot();
}
}
giveRewards();
clearPlayers();
if(particleRefreshSched != null) {
particleRefreshSched.task.cancel();
}
setArenaState(ArenaState.RESTARTING);
}
setTimer(getTimer() - 1);
break;
case RESTARTING:
setTimer(14);
setVoting(false);
receivedVoteItems = false;
setOptionValue(ArenaOption.IN_PLOT_CHECKER, 0);
setArenaState(ArenaState.WAITING_FOR_PLAYERS);
topList.clear();
//clear plot members
for(Plot plot : getPlotManager().getPlots()) {
plot.getMembers().clear();
}
setThemeTimerSet(false);
setThemeVoteTime(true);
voteMenu.resetPoll();
for(Player spectator : new ArrayList<>(getSpectators())) {
ArenaManager.leaveAttempt(spectator, this);
}
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.BUNGEE_ENABLED)) {
if(ConfigUtils.getConfig(getPlugin(), "bungee").getBoolean("Shutdown-When-Game-Ends")) {
getPlugin().getServer().shutdown();
}
ArenaRegistry.shuffleBungeeArena();
for(Player player : Bukkit.getOnlinePlayers()) {
ArenaManager.joinAttempt(player, ArenaRegistry.getArenas().get(ArenaRegistry.getBungeeArena()));
}
}
}
}
@Override
public void updateBossBar() {
if(getGameBar() == null) {
return;
}
switch(getArenaState()) {
case WAITING_FOR_PLAYERS:
getGameBar().setTitle(getPlugin().getChatManager().colorMessage("Bossbar.Waiting-For-Players"));
break;
case STARTING:
getGameBar().setTitle(getPlugin().getChatManager().colorMessage("Bossbar.Starting-In").replace("%time%", Integer.toString(getTimer())));
break;
case IN_GAME:
getGameBar().setTitle(getPlugin().getChatManager().colorMessage(voteTime ? "Bossbar.Vote-Time-Left" : "Bossbar.Time-Left")
.replace("%time%", Integer.toString(getTimer())));
break;
default:
break;
}
}
@Override
public void distributePlots() {
//clear plots before distribution to avoid problems
for(Plot plot : getPlotManager().getPlots()) {
plot.getMembers().clear();
}
List<Player> players = new ArrayList<>(getPlayers());
for(Plot plot : getPlotManager().getPlots()) {
if(players.isEmpty()) {
break;
}
Player first = players.get(0);
User user = plugin.getUserManager().getUser(first);
if(user.isSpectator()) {
continue;
}
plot.addMember(first, this, true);
user.setCurrentPlot(plot);
players.remove(0);
}
if(!players.isEmpty()) {
MessageUtils.errorOccurred();
Debugger.sendConsoleMsg("&c[Build Battle] [PLOT WARNING] Not enough plots in arena " + getID() + "! Lacks " + players.size() + " plots");
Debugger.sendConsoleMsg("&c[PLOT WARNING] Required " + getPlayers().size() + " but have " + getPlotManager().getPlots().size());
Debugger.sendConsoleMsg("&c[PLOT WARNING] Instance was stopped!");
ArenaManager.stopGame(false, this);
}
getPlotManager().teleportToPlots();
}
public void voteRoutine() {
if(!queue.isEmpty()) {
setTimer(getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.PLOT_VOTE, this));
Plot plot = queue.poll();
while(plot == null && !queue.isEmpty()) {
// should not happen anymore... to be removed
System.out.print("A PLAYER HAS NO PLOT!");
plot = queue.poll();
}
if(queue.isEmpty() && plot == null) {
votingPlot = null;
return;
}
// getPlotManager().teleportAllToPlot(plotManager.getPlot(player.getUniqueId()));
votingPlot = plot;
String message = getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Voting-For-Player-Plot").replace("%PLAYER%", plot.getFormattedMembers());
Location teleportLoc = votingPlot.getTeleportLocation();
for(Player p : getPlayers()) {
p.teleport(teleportLoc);
p.setPlayerWeather(votingPlot.getWeatherType());
p.setPlayerTime(Plot.Time.format(votingPlot.getTime(), p.getWorld().getTime()), false);
if(getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.ANNOUNCE_PLOTOWNER_LATER)) {
p.sendMessage(getPlugin().getChatManager().getPrefix() + getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Vote-For-Next-Plot"));
} else {
String owner = getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Plot-Owner-Title");
owner = formatWinners(votingPlot, owner);
VersionUtils.sendTitle(p, owner, 5, 40, 5);
p.sendMessage(getPlugin().getChatManager().getPrefix() + message);
}
}
for(Player spectator : getSpectators()) {
spectator.teleport(teleportLoc);
spectator.setPlayerWeather(votingPlot.getWeatherType());
spectator.setPlayerTime(Plot.Time.format(votingPlot.getTime(), spectator.getWorld().getTime()), false);
String owner = getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Plot-Owner-Title");
owner = formatWinners(votingPlot, owner);
VersionUtils.sendTitle(spectator, owner, 5, 40, 5);
spectator.sendMessage(getPlugin().getChatManager().getPrefix() + message);
}
}
}
public String formatWinners(Plot plot, String string) {
return string.replace("%player%", plot.getFormattedMembers());
}
public void voteForNextPlot() {
if(votingPlot != null) {
if(votingPlot.getPoints() == 0) {
for(Player player : getPlayers()) {
User user = getPlugin().getUserManager().getUser(player);
if(!votingPlot.getMembers().contains(player))
votingPlot.setPoints(votingPlot.getPoints() + user.getStat(StatsStorage.StatisticType.LOCAL_POINTS));
user.setStat(StatsStorage.StatisticType.LOCAL_POINTS, 3);
if(!player.getInventory().contains(plugin.getVoteItems().getReportItem())) {
player.getInventory().setItem(plugin.getVoteItems().getReportVoteItem().getSlot(), plugin.getVoteItems().getReportVoteItem().getItemStack());
player.updateInventory();
}
}
}
if(!votingPlot.getMembers().isEmpty() && getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.ANNOUNCE_PLOTOWNER_LATER)) {
String message = getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Voted-For-Player-Plot").replace("%PLAYER%", votingPlot.getFormattedMembers());
for(Player p : getPlayers()) {
String owner = getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Plot-Owner-Title");
owner = formatWinners(votingPlot, owner);
VersionUtils.sendTitle(p, owner, 5, 40, 5);
p.sendMessage(getPlugin().getChatManager().getPrefix() + message);
}
}
}
voteRoutine();
}
/**
* Get plot where players are voting currently
*
* @return Plot object where players are voting
*/
public Plot getVotingPlot() {
return votingPlot;
}
private void announceResults() {
List<String> messages = LanguageManager.getLanguageList("In-Game.Messages.Voting-Messages.Summary");
List<String> formattedSummary = new ArrayList<>();
for(String summary : messages) {
String message = getPlugin().getChatManager().colorRawMessage(summary);
for(int i = 1; i < 4; i++) {
String access = "One";
switch(i) {
case 2:
access = "Two";
break;
case 3:
access = "Three";
break;
default:
break;
}
String accessLower = access.toLowerCase();
if(message.contains("%place_" + accessLower + "%")) {
List<Player> list = topList.get(i);
if(list != null && !list.isEmpty()) {
Plot plot = getPlotManager().getPlot(list.get(0));
message = StringUtils.replace(message, "%place_" + accessLower + "%", getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Place-" + access)
.replace("%player%", formatWinners(list))
.replace("%number%", plot == null ? "" : Integer.toString(plot.getPoints())));
} else {
message = StringUtils.replace(message, "%place_" + accessLower + "%", getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Place-" + access)
.replace("%player%", "None")
.replace("%number%", "none"));
}
}
}
formattedSummary.add(message);
}
getAllArenaPlayers().forEach(player -> formattedSummary.forEach(msg -> MiscUtils.sendCenteredMessage(player, msg)));
for(Map.Entry<Integer, List<Player>> map : topList.entrySet()) {
for(Player p : map.getValue()) {
if(map.getKey() > 3) {
p.sendMessage(getPlugin().getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Summary-Other-Place").replace("%number%", Integer.toString(map.getKey())));
}
User user = getPlugin().getUserManager().getUser(p);
Plot plot = getPlotManager().getPlot(p);
if(plot != null) {
if(plot.getPoints() > user.getStat(StatsStorage.StatisticType.HIGHEST_POINTS)) {
user.setStat(StatsStorage.StatisticType.HIGHEST_POINTS, plot.getPoints());
}
user.addStat(StatsStorage.StatisticType.TOTAL_POINTS_EARNED, plot.getPoints());
}
if(map.getKey() != 1) {
user.addStat(StatsStorage.StatisticType.LOSES, 1);
continue;
}
user.addStat(StatsStorage.StatisticType.WINS, 1);
if(plot != null && plot.getPoints() > user.getStat(StatsStorage.StatisticType.HIGHEST_WIN)) {
user.setStat(StatsStorage.StatisticType.HIGHEST_WIN, plot.getPoints());
}
}
}
}
private String formatWinners(final List<Player> winners) {
List<Player> players = new ArrayList<>(winners);
StringBuilder builder = new StringBuilder(players.get(0).getName());
if(players.size() == 1) {
return builder.toString();
}
players.remove(0);
for(Player p : players) {
builder.append(" & ").append(p.getName());
}
return builder.toString();
}
private void calculateResults() {
for(int b = 1; b <= getPlayers().size(); b++) {
topList.put(b, new ArrayList<>());
}
for(Plot buildPlot : getPlotManager().getPlots()) {
long i = buildPlot.getPoints();
for(Map.Entry<Integer, List<Player>> map : new HashMap<>(topList).entrySet()) {
Player first = map.getValue().isEmpty() ? null : map.getValue().get(0);
Plot plot = getPlotManager().getPlot(first);
if(plot == null) {
topList.put(map.getKey(), buildPlot.getMembers());
break;
}
if(i > plot.getPoints()) {
moveScore(map.getKey(), buildPlot.getMembers());
break;
}
if(i == plot.getPoints()) {
List<Player> winners = topList.getOrDefault(map.getKey(), new ArrayList<>());
winners.addAll(buildPlot.getMembers());
topList.put(map.getKey(), winners);
break;
}
}
}
}
private void moveScore(int pos, List<Player> owners) {
List<Player> after = topList.getOrDefault(pos, new ArrayList<>());
topList.put(pos, owners);
if(pos <= getPlayers().size() && !after.isEmpty()) {
moveScore(pos + 1, after);
}
}
public boolean enoughPlayersToContinue() {
return getPlayers().size() >= 2;
}
@Override
public void giveRewards() {
for(int i = 1; i <= topList.size(); i++) {
List<Player> list = topList.get(i);
if(list != null) {
for(Player player : list) {
getPlugin().getRewardsHandler().performReward(player, Reward.RewardType.PLACE, i);
}
}
}
getPlugin().getRewardsHandler().performReward(this, Reward.RewardType.END_GAME);
}
public boolean isThemeVoteTime() {
return themeVoteTime;
}
public void setThemeVoteTime(boolean themeVoteTime) {
this.themeVoteTime = themeVoteTime;
}
public boolean isThemeTimerSet() {
return themeTimerSet;
}
public void setThemeTimerSet(boolean themeTimerSet) {
this.themeTimerSet = themeTimerSet;
}
}
@@ -1,103 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.impl;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.arena.options.ArenaOption;
import plugily.projects.buildbattle.utils.Debugger;
import java.util.Comparator;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class TeamArena extends SoloArena {
public TeamArena(String id, Main plugin) {
super(id, plugin);
}
@Override
public void setMinimumPlayers(int amount) {
if(amount <= getPlotSize()) {
Debugger.debug(Debugger.Level.WARN, "Minimum players amount for TEAM game mode arena cannot be less than 3! Setting amount to 3!");
setOptionValue(ArenaOption.MINIMUM_PLAYERS, 3);
return;
}
super.setMinimumPlayers(amount);
}
@Override
public void distributePlots() {
for(Player player : getPlayers()) {
// get base with min players
Plot minPlayers = getPlotManager().getPlots().stream().min(Comparator.comparing(Plot::getMembersSize)).get();
// add player to min base if he got no base
Plot playerPlot = getPlotManager().getPlot(player);
if(playerPlot == null) {
minPlayers.addMember(player, this, true);
}
// fallback
if(playerPlot == null) {
Plot firstPlot = getPlotManager().getPlots().get(0);
firstPlot.addMember(player, this, true);
}
}
//check if not only one plot got players
Plot maxPlayers = getPlotManager().getPlots().stream().max(Comparator.comparing(Plot::getMembersSize)).get();
Plot minPlayers = getPlotManager().getPlots().stream().min(Comparator.comparing(Plot::getMembersSize)).get();
if(maxPlayers.getMembersSize() == getPlayers().size()) {
for(int i = 0; i < maxPlayers.getMembersSize() / 2; i++) {
Player move = maxPlayers.getMembers().get(i);
minPlayers.addMember(move, this, true);
maxPlayers.removeMember(move);
}
}
getPlotManager().teleportToPlots();
/*if (!players.isEmpty()) {
MessageUtils.errorOccurred();
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[Build Battle] [PLOT WARNING] Not enough plots in arena " + getID() + "!");
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[PLOT WARNING] Required " + Math.ceil((double) getPlayers().size() / 2) + " but have " + getPlotManager().getPlots().size());
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[PLOT WARNING] Instance was stopped!");
ArenaManager.stopGame(false, this);
}*/
}
@Override
public boolean enoughPlayersToContinue() {
int size = getPlayers().size();
if(size > getPlotSize()) {
return true;
}
if(size == getPlotSize()) {
return !getPlotManager().getPlot(getPlayers().get(0)).getMembers().containsAll(getPlayers());
}
return false;
}
}
@@ -1,130 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.managers;
import me.clip.placeholderapi.PlaceholderAPI;
import me.tigerhix.lib.scoreboard.common.EntryBuilder;
import me.tigerhix.lib.scoreboard.type.Entry;
import org.apache.commons.lang.StringUtils;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.impl.GuessTheBuildArena;
import plugily.projects.buildbattle.handlers.language.LanguageManager;
import plugily.projects.buildbattle.user.User;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class GuessTheBuildScoreboardManager extends ScoreboardManager {
private final Map<String, List<String>> scoreboardContents = new HashMap<>();
private final GuessTheBuildArena arena;
public GuessTheBuildScoreboardManager(BaseArena arena) {
super(arena);
this.arena = (GuessTheBuildArena) arena;
for(ArenaState state : ArenaState.values()) {
//not registering RESTARTING state and registering IN_GAME and ENDING later
if(state == ArenaState.RESTARTING || state == ArenaState.IN_GAME || state == ArenaState.ENDING) {
continue;
}
//todo migrator
List<String> lines = LanguageManager.getLanguageList("Scoreboard.Content." + state.getFormattedName());
scoreboardContents.put(state.getFormattedName(), lines);
}
List<String> playing = LanguageManager.getLanguageList("Scoreboard.Content.Playing-States." + BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix());
List<String> ending = LanguageManager.getLanguageList("Scoreboard.Content.Ending-States." + BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix());
//todo locale
scoreboardContents.put(ArenaState.IN_GAME.getFormattedName() + "_" + BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix(), playing);
scoreboardContents.put(ArenaState.ENDING.getFormattedName() + "_" + BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix(), ending);
}
//todo maybe not needed and private
@Override
public List<Entry> formatScoreboard(User user) {
EntryBuilder builder = new EntryBuilder();
List<String> lines = scoreboardContents.get(arena.getArenaState().getFormattedName());
if(arena.getArenaState() == ArenaState.IN_GAME || arena.getArenaState() == ArenaState.ENDING) {
lines = scoreboardContents.get(arena.getArenaState().getFormattedName() + "_" + BaseArena.ArenaType.GUESS_THE_BUILD.getPrefix());
}
if (lines == null) {
return builder.build();
}
for(String line : lines) {
builder.next(formatScoreboardLine(line, user));
}
return builder.build();
}
@Override
public String formatScoreboardLine(String string, User user) {
Player player = user.getPlayer();
String returnString = string;
returnString = StringUtils.replace(returnString, "%PLAYERS%", Integer.toString(arena.getPlayers().size()));
returnString = StringUtils.replace(returnString, "%PLAYER%", player.getName());
if(arena.isThemeSet()) {
returnString = StringUtils.replace(returnString, "%CURRENT_TIMER%", getPlugin().getChatManager().colorMessage("Scoreboard.GTB-Current-Timer.Build-Time"));
} else {
returnString = StringUtils.replace(returnString, "%CURRENT_TIMER%", getPlugin().getChatManager().colorMessage("Scoreboard.GTB-Current-Timer.Starts-In"));
}
if(arena.getCurrentBuilder() != null) {
if((arena.getCurrentBuilder().equals(player) && arena.getCurrentTheme() != null) || arena.getWhoGuessed().contains(player)) {
returnString = StringUtils.replace(returnString, "%THEME%", arena.getCurrentTheme().getTheme());
} else {
returnString = StringUtils.replace(returnString, "%THEME%", getPlugin().getChatManager().colorMessage("Scoreboard.Theme-Unknown"));
}
returnString = StringUtils.replace(returnString, "%BUILDER%", arena.getCurrentBuilder().getName());
} else {
returnString = StringUtils.replace(returnString, "%THEME%", getPlugin().getChatManager().colorMessage("Scoreboard.Theme-Unknown"));
returnString = StringUtils.replace(returnString, "%BUILDER%", getPlugin().getChatManager().colorMessage("Scoreboard.Theme-Unknown"));
}
if(arena.getArenaState() == ArenaState.IN_GAME || arena.getArenaState() == ArenaState.ENDING) {
int max = arena.getArenaState() == ArenaState.IN_GAME ? 3 : 10;
List<Map.Entry<Player, Integer>> list = new ArrayList<>(arena.getPlayersPoints().entrySet());
int size = list.size();
for(int i = 0; i <= max; i++) {
if(size - 1 < i) {
returnString = StringUtils.replace(returnString, "%" + (i + 1) + "%", "None");
returnString = StringUtils.replace(returnString, "%" + (i + 1) + "_PTS%", "0");
continue;
}
Map.Entry<Player, Integer> entry = list.get(i);
returnString = StringUtils.replace(returnString, "%" + (i + 1) + "%", entry.getKey().getName());
returnString = StringUtils.replace(returnString, "%" + (i + 1) + "_PTS%", String.valueOf(entry.getValue()));
}
}
returnString = replaceValues(returnString);
if(getPlugin().getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
returnString = PlaceholderAPI.setPlaceholders(player, returnString);
}
returnString = getPlugin().getChatManager().colorRawMessage(returnString);
return returnString;
}
}
@@ -0,0 +1,71 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.managers;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.minigamesbox.classic.arena.managers.PluginMapRestorerManager;
public class MapRestorerManager extends PluginMapRestorerManager {
public final BaseArena arena;
public MapRestorerManager(BaseArena arena) {
super(arena);
this.arena = arena;
}
@Override
public void fullyRestoreArena() {
arena.cleanUpArena();
clearPlots();
cancelParticleRefresh();
arena.setArenaOption("IN_PLOT_CHECKER", 0);
arena.setArenaInGameState(BaseArena.ArenaInGameState.NONE);
super.fullyRestoreArena();
}
private void clearPlots() {
for (Plot plot : arena.getPlotManager().getPlots()) {
plot.fullyResetPlot();
plot.getMembers().clear();
}
}
private void cancelParticleRefresh() {
if (arena.getParticleRefreshScheduler() != null) {
arena.getParticleRefreshScheduler().cancelTask();
}
}
}
@@ -0,0 +1,190 @@
package plugily.projects.buildbattle.arena.managers;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.handlers.misc.TrueOGBoard;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.classic.arena.managers.BossbarManager;
// The arena boss bar as a phase timer with true-og.net in its title.
public class PhaseBossbarManager extends BossbarManager {
private static final String SITE = " &8| &e"
+ ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', TrueOGBoard.FOOTER));
private final BaseArena arena;
// One bar per arena; every player and spectator watches the same phase.
private final BossBar bar;
public PhaseBossbarManager(BaseArena arena) {
super(arena);
this.arena = arena;
this.bar = Bukkit.createBossBar("", BarColor.WHITE, BarStyle.SOLID);
}
@Override
public void doBarAction(IPluginArena.IBarAction action, Player player) {
if (!arena.getPlugin().getConfigPreferences().getOption("BOSSBAR")) {
return;
}
if (action == IPluginArena.IBarAction.ADD) {
bar.addPlayer(player);
bossBarUpdate();
} else {
bar.removePlayer(player);
}
}
// Called once per arena second, after the state handlers have run.
@Override
public void bossBarUpdate() {
if (bar.getPlayers().isEmpty()) {
return;
}
bar.setColor(color());
bar.setTitle(ChatColor.translateAlternateColorCodes('&', title() + SITE));
setProgress(progress());
}
@Override
public void setProgress(double progress) {
bar.setProgress(Math.max(0.0, Math.min(1.0, progress)));
}
public void removeAll() {
bar.removeAll();
}
private String title() {
final String clock = " &f" + TrueOGBoard.clock(arena.getTimer());
switch (arena.getArenaState()) {
case WAITING_FOR_PLAYERS:
return "&eWaiting for players &7(" + arena.getPlayers().size() + "/" + arena.getMinimumPlayers() + ")";
case STARTING:
case FULL_GAME:
return "&aStarting in" + clock;
case IN_GAME:
return "&6" + phaseName() + clock;
case ENDING:
return "&cGame over" + clock;
case RESTARTING:
return "&cRestarting" + clock;
default:
return "&e" + TrueOGBoard.fit(arena.getMapName(), 32);
}
}
// Guess The Build reuses the build states for pick, guess and round break.
private String phaseName() {
boolean guess = arena.getArenaType() == BaseArena.ArenaType.GUESS_THE_BUILD;
switch (arena.getArenaInGameState()) {
case THEME_VOTING:
return guess ? "Builder picks a theme" : "Theme vote" + round();
case BUILD_TIME:
return guess ? "Guess the build" : "Building" + round();
case PLOT_VOTING:
return guess ? "Next round in" : "Plot vote" + round();
default:
return "Starting";
}
}
// " 2/3" for a multi-round Classic or Teams match, otherwise nothing.
private String round() {
if (!(arena instanceof BuildArena) || ((BuildArena) arena).getRounds() <= 1) {
return "";
}
BuildArena build = (BuildArena) arena;
return " " + build.getRound() + "/" + build.getRounds();
}
private BarColor color() {
IArenaState state = arena.getArenaState();
if (state == IArenaState.IN_GAME) {
switch (arena.getArenaInGameState()) {
case BUILD_TIME:
return BarColor.GREEN;
case PLOT_VOTING:
return BarColor.BLUE;
default:
return BarColor.YELLOW;
}
}
if (state == IArenaState.ENDING || state == IArenaState.RESTARTING) {
return BarColor.RED;
}
return state == IArenaState.WAITING_FOR_PLAYERS ? BarColor.WHITE : BarColor.GREEN;
}
// Full while waiting, otherwise the share of the phase still to run.
private double progress() {
if (arena.getArenaState() == IArenaState.WAITING_FOR_PLAYERS) {
return 1.0;
}
int length = arena.getPhaseLength();
if (length <= 0) {
return 1.0;
}
return (double) arena.getTimer() / length;
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,174 +20,358 @@
package plugily.projects.buildbattle.arena.managers;
import me.clip.placeholderapi.PlaceholderAPI;
import me.tigerhix.lib.scoreboard.ScoreboardLib;
import me.tigerhix.lib.scoreboard.common.EntryBuilder;
import me.tigerhix.lib.scoreboard.type.Entry;
import me.tigerhix.lib.scoreboard.type.Scoreboard;
import me.tigerhix.lib.scoreboard.type.ScoreboardHandler;
import org.apache.commons.lang.StringUtils;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.impl.SoloArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.handlers.language.LanguageManager;
import plugily.projects.buildbattle.user.User;
import plugily.projects.commonsbox.string.StringFormatUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class ScoreboardManager {
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
private static final Main plugin = JavaPlugin.getPlugin(Main.class);
private final Map<String, List<String>> scoreboardContents = new HashMap<>();
private final List<Scoreboard> scoreboards = new ArrayList<>();
private final String boardTitle = plugin.getChatManager().colorMessage("Scoreboard.Title");
private final BaseArena arena;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.arena.GuessArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.handlers.misc.ScoreboardOGBridge;
import plugily.projects.buildbattle.handlers.misc.TrueOGBoard;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.managers.PluginScoreboardManager;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
// The arena sidebar in the Scoreboard-OG house style. Lines are built here rather
// than read from language.yml so every card fits 1.8 clients and stays branded.
public class ScoreboardManager extends PluginScoreboardManager {
// Renders the §x hex form MiniGamesBox's colorizer emits.
private static final LegacyComponentSerializer SECTION_SERIALIZER = LegacyComponentSerializer.builder()
.character('§').hexColors().useUnusualXRepeatedCharacterHexFormat().build();
private final BaseArena arena;
// Players whose sidebar Scoreboard-OG renders for this arena.
private final Set<UUID> claimed = ConcurrentHashMap.newKeySet();
public ScoreboardManager(PluginArena arena) {
super(arena);
this.arena = (BaseArena) arena;
public ScoreboardManager(BaseArena arena) {
this.arena = arena;
for(ArenaState state : ArenaState.values()) {
//not registering RESTARTING state and registering IN_GAME and ENDING later
if(state == ArenaState.RESTARTING || state == ArenaState.IN_GAME || state == ArenaState.ENDING) {
continue;
}
//todo migrator
List<String> lines = LanguageManager.getLanguageList("Scoreboard.Content." + state.getFormattedName());
scoreboardContents.put(state.getFormattedName(), lines);
}
for(BaseArena.ArenaType type : BaseArena.ArenaType.values()) {
List<String> playing = LanguageManager.getLanguageList("Scoreboard.Content.Playing-States." + type.getPrefix());
List<String> ending = LanguageManager.getLanguageList("Scoreboard.Content.Ending-States." + type.getPrefix());
//todo locale
scoreboardContents.put(ArenaState.IN_GAME.getFormattedName() + "_" + type.getPrefix(), playing);
scoreboardContents.put(ArenaState.ENDING.getFormattedName() + "_" + type.getPrefix(), ending);
}
}
/**
* Creates arena scoreboard for target user
*
* @param user user that represents game player
* @see User
*/
public void createScoreboard(User user) {
Scoreboard scoreboard = ScoreboardLib.createScoreboard(user.getPlayer()).setHandler(new ScoreboardHandler() {
@Override
public String getTitle(Player player) {
return boardTitle;
}
// With Scoreboard-OG present the arena board rides its sidebar and the network
// board returns by itself on leave. Without it the MiniGamesBox board is used.
@Override
public void createScoreboard(IUser user) {
@Override
public List<Entry> getEntries(Player player) {
return formatScoreboard(user);
}
});
scoreboard.activate();
scoreboards.add(scoreboard);
}
Player player = user.getPlayer();
if (player == null || !ScoreboardOGBridge.isAvailable()) {
/**
* Removes scoreboard of user
*
* @param user user that represents game player
* @see User
*/
public void removeScoreboard(User user) {
for(Scoreboard board : scoreboards) {
if(board.getHolder().equals(user.getPlayer())) {
scoreboards.remove(board);
board.deactivate();
return;
}
}
}
super.createScoreboard(user);
return;
/**
* Forces all scoreboards to deactivate.
*/
public void stopAllScoreboards() {
scoreboards.forEach(Scoreboard::deactivate);
scoreboards.clear();
}
public List<Entry> formatScoreboard(User user) {
EntryBuilder builder = new EntryBuilder();
List<String> lines = scoreboardContents.get(arena.getArenaState().getFormattedName());
if(arena.getArenaState() == ArenaState.IN_GAME || arena.getArenaState() == ArenaState.ENDING) {
lines = scoreboardContents.get(arena.getArenaState().getFormattedName() + "_" + arena.getArenaType().getPrefix());
}
if(lines != null) {
for(String line : lines) {
builder.next(formatScoreboardLine(line, user));
}
}
return builder.build();
}
public String formatScoreboardLine(String string, User user) {
Player player = user.getPlayer();
String returnString = string;
returnString = StringUtils.replace(returnString, "%PLAYERS%", Integer.toString(arena.getPlayers().size()));
returnString = StringUtils.replace(returnString, "%PLAYER%", player.getName());
returnString = replaceValues(returnString);
if(((SoloArena) arena).isThemeVoteTime()) {
returnString = StringUtils.replace(returnString, "%THEME%", plugin.getChatManager().colorMessage("In-Game.No-Theme-Yet"));
returnString = StringUtils.replace(returnString, "%TEAMMATE%", plugin.getChatManager().colorMessage("In-Game.Nobody"));
} else {
returnString = StringUtils.replace(returnString, "%THEME%", arena.getTheme());
Plot plot = arena.getPlotManager().getPlot(player);
if(arena.getArenaType() == BaseArena.ArenaType.TEAM && plot != null) {
if(plot.getMembers().size() > 1) {
StringBuilder members = new StringBuilder();
plot.getMembers().forEach(p -> members.append(p.getName()).append(" & "));
members.deleteCharAt(members.length() - 2);
returnString = StringUtils.replace(returnString, "%TEAMMATE%", members.toString());
} else {
returnString = StringUtils.replace(returnString, "%TEAMMATE%", plugin.getChatManager().colorMessage("In-Game.Nobody"));
}
}
claimed.add(player.getUniqueId());
ScoreboardOGBridge.claim(player, this::title, this::lines);
}
if(plugin.getServer().getPluginManager().isPluginEnabled("PlaceholderAPI")) {
returnString = PlaceholderAPI.setPlaceholders(player, returnString);
// Scoreboard-OG polls the provider itself, so only the FastBoards need pushing.
@Override
public void updateScoreboards() {
if (!ScoreboardOGBridge.isAvailable()) {
super.updateScoreboards();
}
}
returnString = plugin.getChatManager().colorRawMessage(returnString);
return returnString;
}
public String replaceValues(String string) {
String returnString = string;
returnString = StringUtils.replace(returnString, "%MIN_PLAYERS%", Integer.toString(arena.getMinimumPlayers()));
returnString = StringUtils.replace(returnString, "%MAX_PLAYERS%", Integer.toString(arena.getMaximumPlayers()));
@Override
public void removeScoreboard(IUser user) {
int timer = arena.getTimer();
Player player = user.getPlayer();
if (player != null && claimed.remove(player.getUniqueId())) {
returnString = StringUtils.replace(returnString, "%TIMER%", Integer.toString(timer));
returnString = StringUtils.replace(returnString, "%TIME_LEFT%", Long.toString(timer));
returnString = StringUtils.replace(returnString, "%FORMATTED_TIME_LEFT%", StringFormatUtils.formatIntoMMSS(timer));
returnString = StringUtils.replace(returnString, "%ARENA_ID%", arena.getID());
returnString = StringUtils.replace(returnString, "%MAPNAME%", arena.getMapName());
return returnString;
}
ScoreboardOGBridge.release(player);
public String getBoardTitle() {
return boardTitle;
}
}
public Main getPlugin() {
return plugin;
}
super.removeScoreboard(user);
}
@Override
public void stopAllScoreboards() {
for (UUID playerId : new ArrayList<>(claimed)) {
Player player = Bukkit.getPlayer(playerId);
if (player != null) {
ScoreboardOGBridge.release(player);
}
}
claimed.clear();
super.stopAllScoreboards();
}
private Component title(Player player) {
return legacy(TrueOGBoard.TITLE);
}
private List<Component> lines(Player player) {
List<Component> out = new ArrayList<>();
for (String line : getScoreboardLines(player)) {
out.add(legacy(line));
}
return out;
}
private static Component legacy(String text) {
if (text == null || text.isEmpty()) {
return Component.empty();
}
return SECTION_SERIALIZER.deserialize(ChatColor.translateAlternateColorCodes('&', text));
}
// Top to bottom in the network board's layout: a blank, labelled blocks split
// by blanks, then the site footer. Also feeds the FastBoard fallback.
@Override
public List<String> getScoreboardLines(Player player) {
List<String> lines = new ArrayList<>();
lines.add("");
IArenaState state = arena.getArenaState();
if (state == IArenaState.IN_GAME) {
if (arena instanceof GuessArena) {
addGuessLines(lines, player, (GuessArena) arena);
} else {
addBuildLines(lines, player);
}
} else if (state == IArenaState.ENDING) {
addEndingLines(lines);
} else if (state == IArenaState.RESTARTING) {
lines.add("&cRestarting...");
} else {
addLobbyLines(lines);
}
lines.add("");
lines.add(TrueOGBoard.FOOTER);
return lines;
}
private void addLobbyLines(List<String> lines) {
lines.add("&6Mode:");
lines.add("&f" + modeName());
lines.add("");
lines.add("&eMap:");
lines.add("&f" + TrueOGBoard.fit(arena.getMapName(), TrueOGBoard.VALUE_WIDTH));
lines.add("");
lines.add("&6Players:");
lines.add("&f" + arena.getPlayers().size() + "&7/&f" + arena.getMaximumPlayers());
lines.add("");
lines.add("&6Starting in:");
IArenaState state = arena.getArenaState();
if (state == IArenaState.STARTING || state == IArenaState.FULL_GAME) {
lines.add("&f" + TrueOGBoard.clock(arena.getTimer()));
} else {
int needed = Math.max(0, arena.getMinimumPlayers() - arena.getPlayers().size());
lines.add(needed == 0 ? "&aReady" : "&7Need " + needed + " more");
}
}
// Classic and Teams: theme, phase and clock, then the player's company.
private void addBuildLines(List<String> lines, Player player) {
lines.add("&eTheme:");
lines.add("&f" + TrueOGBoard.fit(theme(player), TrueOGBoard.VALUE_WIDTH));
lines.add("");
lines.add("&6Phase:");
lines.add("&f" + phaseName());
lines.add("&6Time: &f" + TrueOGBoard.clock(arena.getTimer()));
if (arena instanceof BuildArena && ((BuildArena) arena).getRounds() > 1) {
BuildArena build = (BuildArena) arena;
lines.add("&6Round: &f" + build.getRound() + "/" + build.getRounds());
}
lines.add("");
if (arena.getArenaType() == BaseArena.ArenaType.TEAM) {
lines.add("&2Teammate:");
lines.add("&f" + TrueOGBoard.fit(teammate(player), TrueOGBoard.VALUE_WIDTH));
} else {
lines.add("&2Players: &f" + arena.getPlayers().size());
}
if (arena.getArenaInGameState() == BaseArena.ArenaInGameState.PLOT_VOTING && arena instanceof BuildArena) {
Plot voting = ((BuildArena) arena).getVotingPlot();
lines.add("");
lines.add("&eViewing:");
lines.add("&f"
+ TrueOGBoard.fit(voting == null ? "???" : voting.getFormattedMembers(), TrueOGBoard.VALUE_WIDTH));
}
}
// Guess The Build: who builds, what the viewer may know, the round clock and
// the viewer's points against the leader.
private void addGuessLines(List<String> lines, Player player, GuessArena guess) {
Plot buildPlot = guess.getBuildPlot();
lines.add("&6Builder:");
lines.add("&f" + TrueOGBoard.fit(
buildPlot == null || buildPlot.getMembers().isEmpty() ? "???" : buildPlot.getFormattedMembers(),
TrueOGBoard.VALUE_WIDTH));
lines.add("");
lines.add("&eTheme:");
lines.add("&f" + TrueOGBoard.fit(theme(player), TrueOGBoard.VALUE_WIDTH));
lines.add("");
lines.add("&6Round: &f" + guess.getRound());
lines.add("&6Time: &f" + TrueOGBoard.clock(arena.getTimer()));
lines.add("");
Plot own = arena.getPlotManager().getPlot(player);
lines.add("&bPoints: &f" + TrueOGBoard.compact(own == null ? 0 : own.getPoints()));
List<Plot> ranking = arena.getPlotManager().getTopPlotsOrder();
if (!ranking.isEmpty() && ranking.get(0).getPoints() > 0) {
lines.add("&6Leader:");
lines.add("&f" + TrueOGBoard.fit(ranking.get(0).getFormattedMembers(), TrueOGBoard.VALUE_WIDTH));
}
}
private void addEndingLines(List<String> lines) {
lines.add("&cGame over!");
lines.add("");
Plot winner = arena.getWinnerPlot();
if (winner == null) {
List<Plot> ranking = arena.getPlotManager().getTopPlotsOrder();
winner = ranking.isEmpty() ? null : ranking.get(0);
}
lines.add("&eWinner:");
lines.add(
"&f" + TrueOGBoard.fit(winner == null ? "???" : winner.getFormattedMembers(), TrueOGBoard.VALUE_WIDTH));
lines.add("&bPoints: &f" + TrueOGBoard.compact(winner == null ? 0 : winner.getPoints()));
}
private String modeName() {
switch (arena.getArenaType()) {
case TEAM:
return "Teams";
case GUESS_THE_BUILD:
return "GuessTheBuild";
default:
return "Solo";
}
}
private String phaseName() {
switch (arena.getArenaInGameState()) {
case THEME_VOTING:
return "Theme vote";
case PLOT_VOTING:
return "Plot vote";
case BUILD_TIME:
return "Building";
default:
return "Starting";
}
}
// The arena placeholder hides the theme from Guess The Build guessers.
private String theme(Player player) {
String theme = new MessageBuilder("%arena_theme%").arena(arena).player(player).build();
return theme == null || theme.isEmpty() ? "???" : ChatColor.stripColor(theme);
}
private String teammate(Player player) {
Plot plot = arena.getPlotFromPlayer(player);
if (plot == null) {
return "Nobody";
}
for (Player member : plot.getMembers()) {
if (!member.equals(player)) {
return member.getName();
}
}
return "Nobody";
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,15 +31,14 @@ import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.api.event.plot.BBPlotResetEvent;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.utils.Utils;
import plugily.projects.commonsbox.minecraft.compat.ServerVersion;
import plugily.projects.commonsbox.minecraft.compat.xseries.XMaterial;
import plugily.projects.commonsbox.minecraft.dimensional.Cuboid;
import plugily.projects.buildbattle.api.event.plot.PlotResetEvent;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.handlers.misc.ChunkManager;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.dimensional.Cuboid;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import java.util.ArrayList;
import java.util.HashMap;
@@ -51,314 +50,489 @@ import java.util.Map;
*/
public class Plot {
private static final Main plugin = JavaPlugin.getPlugin(Main.class);
private final Map<Location, String> particles = new HashMap<>();
private final XMaterial defaultFloor;
private final Map<Location, String> particles = new HashMap<>();
private final XMaterial defaultFloor;
private final BaseArena arena;
private Cuboid cuboid;
private int points = 0;
// Points from the round being judged; guards against double counting.
private int roundPoints = 0;
private List<Player> members = new ArrayList<>();
private Time time = Time.WORLD_TIME;
private final Biome plotDefaultBiome;
private WeatherType weatherType = WeatherType.CLEAR;
private int entities = 0;
private final BaseArena arena;
private Cuboid cuboid;
private int points = 0;
private List<Player> members = new ArrayList<>();
private Time time = Time.WORLD_TIME;
private final Biome plotDefaultBiome;
private WeatherType weatherType = WeatherType.CLEAR;
private int entities = 0;
public Plot(BaseArena arena, Biome biome) {
public Plot(BaseArena arena, Biome biome) {
this.arena = arena;
plotDefaultBiome = biome;
defaultFloor = XMaterial.matchXMaterial(plugin.getConfig().getString("Default-Floor-Material-Name", "LOG")
.toUpperCase()).orElse(XMaterial.OAK_LOG);
}
this.arena = arena;
plotDefaultBiome = biome;
defaultFloor = XMaterial.matchXMaterial(
arena.getPlugin().getConfig().getString("Floor.Material", "LOG").toUpperCase(java.util.Locale.ENGLISH))
.orElse(XMaterial.OAK_LOG);
public int getEntities() {
return entities;
}
public void addEntity() {
entities++;
}
public void removeEntity() {
if(entities > 0) {
entities--;
}
}
public Map<Location, String> getParticles() {
return particles;
}
public Biome getPlotDefaultBiome() {
return plotDefaultBiome;
}
public WeatherType getWeatherType() {
return weatherType;
}
public void setWeatherType(WeatherType weatherType) {
this.weatherType = weatherType;
}
public Time getTime() {
return time;
}
public void setTime(Time time) {
this.time = time;
}
public Cuboid getCuboid() {
return cuboid;
}
public void setCuboid(Cuboid cuboid) {
this.cuboid = cuboid;
}
@NotNull
public List<Player> getMembers() {
return members;
}
@NotNull
public String getFormattedMembers() {
if(members.size() >= 1) {
StringBuilder member = new StringBuilder();
members.forEach(player -> member.append(player.getName()).append(" & "));
return member.substring(0, member.length() - 3);
} else {
return "PLAYER_NOT_FOUND";
}
}
public int getMembersSize() {
return members.size();
}
public boolean addMember(Player player, BaseArena playerArena, boolean silent) {
if(playerArena == null) {
return false;
}
if(members.contains(player)) {
if(!silent) player.sendMessage(plugin.getChatManager().colorMessage("Plots.Team.Member"));
return false;
public int getEntities() {
return entities;
}
if(members.size() >= playerArena.getPlotSize()) {
if(!silent) player.sendMessage(plugin.getChatManager().colorMessage("Plots.Team.Full"));
return false;
public void addEntity() {
entities++;
}
Plot plot = playerArena.getPlotManager().getPlot(player);
if(plot != null) {
plot.removeMember(player);
}
members.add(player);
plugin.getUserManager().getUser(player).setCurrentPlot(this);
return true;
}
public void removeEntity() {
public void removeMember(Player player) {
members.remove(player);
}
if (entities > 0) {
public void fullyResetPlot() {
resetPlot();
entities--;
for(Player p : members) {
plugin.getUserManager().getUser(p).setCurrentPlot(null);
}
setPoints(0);
members.clear();
particles.clear();
}
public void resetPlot() {
if(cuboid == null) {
return;
}
for(Block block : cuboid.blockList()) {
//to ensure 1.14 blocks support (that will be seen as air in api-version 1.13)
//we set all blocks to air so 1.14 ones will update too
block.setType(Material.AIR);
}
particles.clear();
for(Player p : members) {
p.resetPlayerWeather();
setWeatherType(p.getPlayerWeather());
p.resetPlayerTime();
}
World centerWorld = cuboid.getCenter().getWorld();
if(centerWorld != null) {
for(Entity entity : centerWorld.getEntities()) {
if(cuboid.isInWithMarge(entity.getLocation(), 5)) {
//deprecated seems not to work with latest builds of citizens
if(plugin.getServer().getPluginManager().isPluginEnabled("Citizens") && CitizensAPI.getNPCRegistry() != null
&& CitizensAPI.getNPCRegistry().isNPC(entity)) {
continue;
}
//citizens also uses metadata, see https://wiki.citizensnpcs.co/API
if(entity.hasMetadata("NPC")) {
continue;
}
if(entity.getType() != EntityType.PLAYER) {
entity.remove();
}
}
}
}
for(Block block : cuboid.blockList()) {
block.setBiome(plotDefaultBiome);
public Map<Location, String> getParticles() {
return particles;
}
for(Chunk chunk : cuboid.chunkList()) {
for(Player p : plugin.getServer().getOnlinePlayers()) {
if(p.getWorld().equals(chunk.getWorld())) {
Utils.sendMapChunk(p, chunk);
public Biome getPlotDefaultBiome() {
return plotDefaultBiome;
}
public WeatherType getWeatherType() {
return weatherType;
}
public void setWeatherType(WeatherType weatherType) {
if (weatherType != null) {
this.weatherType = weatherType;
}
}
}
changeFloor(defaultFloor.parseMaterial());
public Time getTime() {
return time;
}
public void setTime(Time time) {
this.time = time;
}
public Cuboid getCuboid() {
return cuboid;
}
public void setCuboid(Cuboid cuboid) {
this.cuboid = cuboid;
}
@NotNull
public List<Player> getMembers() {
return members;
}
@NotNull
public String getFormattedMembers() {
if (!members.isEmpty()) {
StringBuilder member = new StringBuilder();
members.forEach(player -> member.append(player.getName()).append(" & "));
return member.substring(0, member.length() - 3);
}
return "PLAYER_NOT_FOUND";
}
public int getMembersSize() {
return members.size();
}
public boolean addMember(Player player, BaseArena playerArena, boolean silent) {
if (playerArena == null) {
return false;
}
if (members.contains(player)) {
if (!silent)
new MessageBuilder("IN_GAME_MESSAGES_PLOT_SELECTOR_MEMBER").asKey().arena(arena).player(player)
.sendPlayer();
return false;
}
if (members.size() >= arena.getArenaOption("PLOT_MEMBER_SIZE")) {
if (!silent)
new MessageBuilder("IN_GAME_MESSAGES_PLOT_SELECTOR_FULL").asKey().prefix().arena(arena).player(player)
.sendPlayer();
return false;
}
Plot plot = playerArena.getPlotManager().getPlot(player);
if (plot != null) {
plot.removeMember(player);
}
members.add(player);
return true;
}
public void removeMember(Player player) {
members.remove(player);
}
public void fullyResetPlot() {
resetPlot();
points = 0;
roundPoints = 0;
members.clear();
particles.clear();
}
public void resetPlot() {
if (cuboid == null) {
return;
}
for (Block block : cuboid.blockList()) {
// to ensure 1.14 blocks support (that will be seen as air in api-version 1.13)
// we set all blocks to air so 1.14 ones will update too
block.setType(Material.AIR);
}
particles.clear();
for (Player p : members) {
p.setPlayerWeather(WeatherType.CLEAR);
p.resetPlayerTime();
}
setTime(Time.WORLD_TIME);
setWeatherType(WeatherType.CLEAR);
World centerWorld = cuboid.getCenter().getWorld();
if (centerWorld != null) {
boolean isCitizensEnabled = arena.getPlugin().getServer().getPluginManager().isPluginEnabled("Citizens");
for (Entity entity : centerWorld.getEntities()) {
if (cuboid.isInWithMarge(entity.getLocation(), 5)) {
// deprecated seems not to work with latest builds of citizens
if (isCitizensEnabled && CitizensAPI.getNPCRegistry() != null
&& CitizensAPI.getNPCRegistry().isNPC(entity))
{
continue;
}
// citizens also uses metadata, see https://wiki.citizensnpcs.co/API
if (entity.hasMetadata("NPC")) {
continue;
}
if (entity.getType() != EntityType.PLAYER) {
entity.remove();
}
}
}
}
for (Block block : cuboid.blockList()) {
block.setBiome(plotDefaultBiome);
}
for (Chunk chunk : cuboid.chunkList()) {
if (ServerVersion.Version.isCurrentEqualOrHigher(ServerVersion.Version.v1_15)) {
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
continue;
}
for (Player p : arena.getPlugin().getServer().getOnlinePlayers()) {
if (p.getWorld().equals(chunk.getWorld())) {
ChunkManager.sendMapChunk(p, chunk);
}
}
}
changeFloor(defaultFloor.parseMaterial());
if (centerWorld != null) {
if (ServerVersion.Version.isCurrentHigher(ServerVersion.Version.v1_15)) {
Location min = cuboid.getMinPoint();
Location max = cuboid.getMaxPoint();
centerWorld.setBiome(min.getBlockX(), Math.min(min.getBlockY(), max.getBlockY()), max.getBlockZ(),
plotDefaultBiome);
} else {
centerWorld.setBiome(cuboid.getMinPoint().getBlockX(), cuboid.getMaxPoint().getBlockZ(),
plotDefaultBiome);
}
}
arena.getPlugin().getServer().getPluginManager().callEvent(new PlotResetEvent(arena, this));
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public void addPoints(int points) {
this.points += points;
roundPoints += points;
}
public int getRoundPoints() {
return roundPoints;
}
// Match points stay; the next round's plot vote starts from zero.
public void resetRoundPoints() {
roundPoints = 0;
}
private void changeFloor(Material material) {
if(centerWorld != null) {
if(ServerVersion.Version.isCurrentHigher(ServerVersion.Version.v1_15_R1)) {
Location min = cuboid.getMinPoint();
Location max = cuboid.getMaxPoint();
int y = Math.min(min.getBlockY(), max.getBlockY());
int y = (int) Math.min(min.getY(), max.getY());
centerWorld.setBiome(min.getBlockX(), y, max.getBlockZ(), plotDefaultBiome);
} else {
centerWorld.setBiome(cuboid.getMinPoint().getBlockX(), cuboid.getMaxPoint().getBlockZ(), plotDefaultBiome);
}
}
int minBlockX = min.getBlockX();
int maxBlockX = max.getBlockX();
plugin.getServer().getPluginManager().callEvent(new BBPlotResetEvent(arena, this));
}
int minBlockZ = min.getBlockZ();
int maxBlockZ = max.getBlockZ();
public int getPoints() {
return points;
}
World maxWorld = max.getWorld();
public void setPoints(int points) {
this.points = points;
}
for (int x = minBlockX; x <= maxBlockX; x++) {
private void changeFloor(Material material) {
Location min = cuboid.getMinPoint();
Location max = cuboid.getMaxPoint();
for (int z = minBlockZ; z <= maxBlockZ; z++) {
int y = (int) Math.min(min.getY(), max.getY());
maxWorld.getBlockAt(x, y, z).setType(material);
int minBlockX = min.getBlockX();
int maxBlockX = max.getBlockX();
}
int minBlockZ = min.getBlockZ();
int maxBlockZ = max.getBlockZ();
World maxWorld = max.getWorld();
for(int x = minBlockX; x <= maxBlockX; x++) {
for(int z = minBlockZ; z <= maxBlockZ; z++) {
maxWorld.getBlockAt(x, y, z).setType(material);
}
}
}
public void changeFloor(Material material, byte data) {
if(material == Material.WATER_BUCKET || material == Material.MILK_BUCKET) {
material = Material.WATER;
}
if(material == Material.LAVA_BUCKET) {
material = Material.LAVA;
}
Location min = cuboid.getMinPoint();
Location max = cuboid.getMaxPoint();
int y = (int) Math.min(min.getY(), max.getY());
int minBlockX = min.getBlockX();
int maxBlockX = max.getBlockX();
int minBlockZ = min.getBlockZ();
int maxBlockZ = max.getBlockZ();
World maxWorld = max.getWorld();
for(int x = minBlockX; x <= maxBlockX; x++) {
for(int z = minBlockZ; z <= maxBlockZ; z++) {
Block block = maxWorld.getBlockAt(x, y, z);
block.setType(material);
if(ServerVersion.Version.isCurrentEqualOrLower(ServerVersion.Version.v1_12_R1)) {
try {
Block.class.getMethod("setData", byte.class).invoke(block, data);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
public Location getTeleportLocation() {
Location tploc = cuboid.getCenter();
while(tploc.getBlock().getType() != Material.AIR || tploc.add(0, 1, 0).getBlock().getType() != Material.AIR) {
tploc = tploc.add(0, 1, 0);
}
boolean enclosed = false;
int counter = 0;
Location location = tploc.clone();
while(counter != 10) {
if(!(location.getBlock().getType() == Material.BARRIER || location.getBlock().getType() == Material.AIR)) {
enclosed = true;
tploc = location;
counter = 9;
}
location.add(0, 1, 0);
counter++;
}
if(enclosed) {
while(tploc.getBlock().getType() != Material.AIR || tploc.add(0, 1, 0).getBlock().getType() != Material.AIR) {
tploc = tploc.add(0, 1, 0);
}
}
return tploc;
}
/**
* Enum that represents current plot time
*/
public enum Time {
WORLD_TIME(-1), DAY(1000), NOON(6000), SUNSET(12000), SUNRISE(23000), NIGHT(13000), MIDNIGHT(18000);
private final long ticks;
Time(long ticks) {
this.ticks = ticks;
}
public static long format(Time time, long currTime) {
return time == Time.WORLD_TIME ? currTime : time.getTicks();
public void changeFloor(Material material, byte data) {
if (material == Material.WATER_BUCKET || material == Material.MILK_BUCKET) {
material = Material.WATER;
}
if (material == Material.LAVA_BUCKET) {
material = Material.LAVA;
}
Location min = cuboid.getMinPoint();
Location max = cuboid.getMaxPoint();
int y = (int) Math.min(min.getY(), max.getY());
int minBlockX = min.getBlockX();
int maxBlockX = max.getBlockX();
int minBlockZ = min.getBlockZ();
int maxBlockZ = max.getBlockZ();
World maxWorld = max.getWorld();
for (int x = minBlockX; x <= maxBlockX; x++) {
for (int z = minBlockZ; z <= maxBlockZ; z++) {
Block block = maxWorld.getBlockAt(x, y, z);
block.setType(material);
if (ServerVersion.Version.isCurrentEqualOrLower(ServerVersion.Version.v1_12)) {
try {
Block.class.getMethod("setData", byte.class).invoke(block, data);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public long getTicks() {
return ticks;
public Location getTeleportLocation() {
Location tploc = cuboid.getCenter();
while (tploc.getBlock().getType() != Material.AIR || tploc.add(0, 1, 0).getBlock().getType() != Material.AIR) {
tploc = tploc.add(0, 1, 0);
}
boolean enclosed = false;
int counter = 0;
Location location = tploc.clone();
while (counter != 10) {
Material type = location.getBlock().getType();
if (!(type == Material.BARRIER || type == Material.AIR)) {
enclosed = true;
tploc = location;
counter = 9;
}
location.add(0, 1, 0);
counter++;
}
if (enclosed) {
while (tploc.getBlock().getType() != Material.AIR
|| tploc.add(0, 1, 0).getBlock().getType() != Material.AIR)
{
tploc = tploc.add(0, 1, 0);
}
}
return tploc;
}
/**
* Enum that represents current plot time
*/
public enum Time {
WORLD_TIME(-1), DAY(1000), NOON(6000), SUNSET(12000), SUNRISE(23000), NIGHT(13000), MIDNIGHT(18000);
private final long ticks;
Time(long ticks) {
this.ticks = ticks;
}
public static long format(Time time, long currTime) {
return time == Time.WORLD_TIME ? currTime : time.ticks;
}
public long getTicks() {
return ticks;
}
}
}
}
@@ -0,0 +1,622 @@
/*
* Derived from the EternalCombat (https://github.com/EternalCodeTeam/EternalCombat) border module
* by the EternalCode Team, licensed under the Apache License, Version 2.0, by way of the
* Duels-OG adaptation by the TrueOG Network.
*
* Modifications by the TrueOG Network for BuildBattle-OG:
* - The legal area is a plot cuboid grown by a grace margin and the wall is the one-block
* shell just outside it on all six faces, instead of the inner face of a PvP region.
* - Blocks are sent with Paper's Player#sendMultiBlockChange instead of PacketEvents and
* restored from the live world instead of a chunk-snapshot cache.
* - EternalCombat's rainbow hue function is kept and mapped onto Bukkit materials.
* - A builder found past the wall is pulled to the nearest legal spot at their own height,
* or to the plot spawn when that is blocked, in place of the region eject.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package plugily.projects.buildbattle.arena.managers.plots;
import io.papermc.paper.math.BlockPosition;
import io.papermc.paper.math.Position;
import org.bukkit.DyeColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.GuessArena;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.dimensional.Cuboid;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import java.awt.Color;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
// Per-viewer wall around the plot being built in, and the pull-back past it.
public class PlotBorderManager implements Listener {
private static final long UPDATE_TICKS = 10L;
private static final String RAINBOW_PREFIX = "RAINBOW_";
private final Main plugin;
private final int grace;
private final int distance;
private final boolean wallEnabled;
// Null for a rainbow wall; otherwise the block every wall point shows.
private BlockData fixedBlock;
// Rainbow palette: one stained block per dye colour.
private final Map<DyeColor, BlockData> palette = new EnumMap<>(DyeColor.class);
private final Map<UUID, Shown> shown = new HashMap<>();
public PlotBorderManager(Main plugin) {
this.plugin = plugin;
FileConfiguration config = plugin.getConfig();
grace = Math.max(0, config.getInt("Plot.Border.Grace", 3));
distance = Math.max(1, config.getInt("Plot.Border.Distance", 8));
wallEnabled = config.getBoolean("Plot.Border.Enabled", true)
&& resolveBlock(config.getString("Plot.Border.Block", "RAINBOW_GLASS"));
plugin.getServer().getPluginManager().registerEvents(this, plugin);
plugin.getServer().getScheduler().runTaskTimer(plugin, this::refreshAll, UPDATE_TICKS, UPDATE_TICKS);
}
// RAINBOW_<FAMILY> builds a dye palette; anything else is a block name.
private boolean resolveBlock(String name) {
String upper = name.toUpperCase(Locale.ROOT);
if (upper.startsWith(RAINBOW_PREFIX)) {
String family = upper.substring(RAINBOW_PREFIX.length());
String suffix = family.equals("GLASS") ? "_STAINED_GLASS" : "_" + family;
for (DyeColor dye : DyeColor.values()) {
Material material = Material.matchMaterial(dye.name() + suffix);
if (material == null || !material.isBlock()) {
plugin.getLogger().warning(
"Plot.Border.Block " + name + " has no " + dye.name() + suffix + "; wall disabled.");
return false;
}
palette.put(dye, material.createBlockData());
}
return true;
}
Material material = Material.matchMaterial(upper);
if (material == null || !material.isBlock()) {
plugin.getLogger().warning("Plot.Border.Block " + name + " is not a block; wall disabled.");
return false;
}
fixedBlock = material.createBlockData();
return true;
}
// A move ending outside the legal box is snapped back; otherwise redraw.
@EventHandler(ignoreCancelled = true)
public void onMove(PlayerMoveEvent event) {
Location from = event.getFrom();
Location to = event.getTo();
if (to == null || (from.getBlockX() == to.getBlockX() && from.getBlockY() == to.getBlockY()
&& from.getBlockZ() == to.getBlockZ()))
{
return;
}
Player player = event.getPlayer();
Confinement confinement = confinementOf(player);
if (confinement == null) {
clear(player);
return;
}
if (!confinement.box.contains(to)) {
if (confinement.box.contains(from)) {
// The wall failed; cancelling puts them back where they were.
event.setCancelled(true);
return;
}
pullBack(player, confinement);
return;
}
update(player, confinement, to);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onTeleport(PlayerTeleportEvent event) {
Location to = event.getTo();
if (to == null) {
return;
}
Player player = event.getPlayer();
Confinement confinement = confinementOf(player);
if (confinement == null || !to.getWorld().equals(confinement.world)) {
clear(player);
return;
}
update(player, confinement, to);
}
// A world change resends chunks, so the client already lost the wall.
@EventHandler
public void onWorldChange(PlayerChangedWorldEvent event) {
shown.remove(event.getPlayer().getUniqueId());
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
shown.remove(event.getPlayer().getUniqueId());
}
// The three-second arena check: anyone beyond the wall is brought back.
public void enforce(Player player) {
Confinement confinement = confinementOf(player);
if (confinement == null) {
return;
}
Location at = player.getLocation();
if (!at.getWorld().equals(confinement.world) || !confinement.box.contains(at)) {
pullBack(player, confinement);
}
}
// Restores every wall still on a client; used on disable.
public void clearAll() {
for (UUID uuid : new HashSet<>(shown.keySet())) {
Player player = plugin.getServer().getPlayer(uuid);
if (player != null) {
clear(player);
} else {
shown.remove(uuid);
}
}
}
private void refreshAll() {
for (Player player : plugin.getServer().getOnlinePlayers()) {
Confinement confinement = confinementOf(player);
if (confinement == null) {
clear(player);
continue;
}
Location at = player.getLocation();
if (!at.getWorld().equals(confinement.world)) {
clear(player);
continue;
}
update(player, confinement, at);
}
}
// The plot a player is held to right now, or null while they may roam.
private Confinement confinementOf(Player player) {
if (plugin.getConfigPreferences().getOption("PLOT_MOVE_OUTSIDE")) {
return null;
}
BaseArena arena = plugin.getArenaRegistry().getArena(player);
if (arena == null || arena.getArenaState() != IArenaState.IN_GAME
|| arena.getArenaInGameState() != BaseArena.ArenaInGameState.BUILD_TIME
|| !arena.getPlayersLeft().contains(player))
{
return null;
}
Plot plot = arena instanceof GuessArena ? ((GuessArena) arena).getBuildPlot() : arena.getPlotFromPlayer(player);
if (plot == null || plot.getCuboid() == null) {
return null;
}
Cuboid cuboid = plot.getCuboid();
Location min = cuboid.getMinPoint();
Location max = cuboid.getMaxPoint();
if (min.getWorld() == null) {
return null;
}
Box box = new Box(min.getBlockX() - grace, min.getBlockY() - grace, min.getBlockZ() - grace,
max.getBlockX() + grace, max.getBlockY() + grace, max.getBlockZ() + grace);
return new Confinement(arena, plot, min.getWorld(), box);
}
// Sends nearby wall points and restores the ones left behind.
private void update(Player player, Confinement confinement, Location at) {
UUID uuid = player.getUniqueId();
Set<BlockPosition> next = wallEnabled ? wallPoints(confinement, at) : Collections.emptySet();
Shown current = shown.get(uuid);
Map<Position, BlockData> changes = new HashMap<>();
if (current != null) {
for (BlockPosition point : current.points) {
if (!next.contains(point)) {
changes.put(point, restoreData(current.world, point));
}
}
}
for (BlockPosition point : next) {
changes.put(point, wallData(point));
}
if (!changes.isEmpty()) {
player.sendMultiBlockChange(changes);
}
if (next.isEmpty()) {
shown.remove(uuid);
} else {
shown.put(uuid, new Shown(confinement.world, next));
}
}
private void clear(Player player) {
Shown current = shown.remove(player.getUniqueId());
if (current == null || !player.getWorld().equals(current.world)) {
return;
}
Map<Position, BlockData> changes = new HashMap<>();
for (BlockPosition point : current.points) {
changes.put(point, restoreData(current.world, point));
}
player.sendMultiBlockChange(changes);
}
// The shell just outside the legal box, clipped to the view range.
private Set<BlockPosition> wallPoints(Confinement confinement, Location at) {
Box box = confinement.box;
int px = at.getBlockX();
int py = at.getBlockY();
int pz = at.getBlockZ();
int x0 = Math.max(box.minX - 1, px - distance);
int x1 = Math.min(box.maxX + 1, px + distance);
int y0 = Math.max(box.minY - 1, py - distance);
int y1 = Math.min(box.maxY + 1, py + distance);
int z0 = Math.max(box.minZ - 1, pz - distance);
int z1 = Math.min(box.maxZ + 1, pz + distance);
Set<BlockPosition> points = new HashSet<>();
if (x0 > x1 || y0 > y1 || z0 > z1) {
return points;
}
for (int x : new int[] { box.minX - 1, box.maxX + 1 }) {
if (x < x0 || x > x1) {
continue;
}
for (int y = y0; y <= y1; y++) {
for (int z = z0; z <= z1; z++) {
addPoint(points, confinement.world, at, x, y, z);
}
}
}
for (int y : new int[] { box.minY - 1, box.maxY + 1 }) {
if (y < y0 || y > y1) {
continue;
}
for (int x = x0; x <= x1; x++) {
for (int z = z0; z <= z1; z++) {
addPoint(points, confinement.world, at, x, y, z);
}
}
}
for (int z : new int[] { box.minZ - 1, box.maxZ + 1 }) {
if (z < z0 || z > z1) {
continue;
}
for (int x = x0; x <= x1; x++) {
for (int y = y0; y <= y1; y++) {
addPoint(points, confinement.world, at, x, y, z);
}
}
}
return points;
}
// Only non-solid blocks in range become wall; real blocks stay.
private void addPoint(Set<BlockPosition> points, World world, Location at, int x, int y, int z) {
double dx = x + 0.5 - at.getX();
double dy = y + 0.5 - at.getY();
double dz = z + 0.5 - at.getZ();
if (dx * dx + dy * dy + dz * dz > (double) distance * distance) {
return;
}
if (world.getBlockAt(x, y, z).getType().isSolid()) {
return;
}
points.add(Position.block(x, y, z));
}
private BlockData wallData(BlockPosition point) {
if (fixedBlock != null) {
return fixedBlock;
}
return palette.get(nearestDye(rainbow(point.blockX(), point.blockY(), point.blockZ())));
}
private static BlockData restoreData(World world, BlockPosition point) {
return world.getBlockAt(point.blockX(), point.blockY(), point.blockZ()).getBlockData();
}
// EternalCombat's hue: a slow sine over x and z, brighter with height.
private static Color rainbow(int x, int y, int z) {
float hue = (float) ((Math.sin(x * 0.05) + Math.cos(z * 0.05)) * 0.5 + 0.5);
float brightness = 0.8f + 0.2f * Math.max(0.0f, Math.min(1.0f, (float) y / 255));
return Color.getHSBColor(hue, 1.0f, brightness);
}
private static DyeColor nearestDye(Color rgb) {
int best = Integer.MAX_VALUE;
DyeColor dye = DyeColor.WHITE;
for (DyeColor candidate : DyeColor.values()) {
org.bukkit.Color color = candidate.getColor();
int delta = Math.abs(color.getRed() - rgb.getRed()) + Math.abs(color.getGreen() - rgb.getGreen())
+ Math.abs(color.getBlue() - rgb.getBlue());
if (delta < best) {
best = delta;
dye = candidate;
}
}
return dye;
}
// Nearest legal spot at the player's height, or the plot spawn if blocked.
private void pullBack(Player player, Confinement confinement) {
Box box = confinement.box;
Location at = player.getLocation();
double x = Math.min(Math.max(at.getX(), box.minX + 0.5), box.maxX + 0.5);
double y = Math.min(Math.max(at.getY(), box.minY), box.maxY - 1.0);
double z = Math.min(Math.max(at.getZ(), box.minZ + 0.5), box.maxZ + 0.5);
Location target = new Location(confinement.world, x, y, z, at.getYaw(), at.getPitch());
if (target.getBlock().getType().isSolid() || target.clone().add(0, 1, 0).getBlock().getType().isSolid()) {
target = confinement.plot.getTeleportLocation();
}
VersionUtils.teleport(player, target);
new MessageBuilder("IN_GAME_MESSAGES_PLOT_PERMISSION_OUTSIDE").asKey().arena(confinement.arena).player(player)
.sendPlayer();
}
// Inclusive block bounds a player may occupy.
private static final class Box {
private final int minX;
private final int minY;
private final int minZ;
private final int maxX;
private final int maxY;
private final int maxZ;
private Box(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
}
private boolean contains(Location location) {
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
return x >= minX && x <= maxX && y >= minY && y <= maxY && z >= minZ && z <= maxZ;
}
}
private static final class Confinement {
private final BaseArena arena;
private final Plot plot;
private final World world;
private final Box box;
private Confinement(BaseArena arena, Plot plot, World world, Box box) {
this.arena = arena;
this.plot = plot;
this.world = world;
this.box = box;
}
}
private static final class Shown {
private final World world;
private final Set<BlockPosition> points;
private Shown(World world, Set<BlockPosition> points) {
this.world = world;
this.points = points;
}
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,134 +21,161 @@
package plugily.projects.buildbattle.arena.managers.plots;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.api.event.plot.BBPlayerPlotReceiveEvent;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.commonsbox.minecraft.compat.ServerVersion.Version;
import plugily.projects.commonsbox.minecraft.dimensional.Cuboid;
import plugily.projects.buildbattle.api.event.plot.PlotPlayerReceiveEvent;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.minigamesbox.classic.utils.dimensional.Cuboid;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* Created by Tom on 17/08/2015.
*/
public class PlotManager {
private final List<Plot> plots = new ArrayList<>();
private final List<Plot> plotsToClear = new ArrayList<>();
private final BaseArena arena;
private final List<Plot> plots = new ArrayList<>();
private final List<Plot> plotsToClear = new ArrayList<>();
private final BaseArena arena;
public PlotManager(BaseArena arena) {
this.arena = arena;
}
public PlotManager(BaseArena arena) {
public void addBuildPlot(Plot buildPlot) {
plots.add(buildPlot);
}
this.arena = arena;
public Plot getPlot(Player player) {
if(player != null) {
for(Plot buildPlot : plots) {
if(buildPlot.getMembers().contains(player)) {
return buildPlot;
}
}
}
return null;
}
public void resetQueuedPlots() {
plotsToClear.forEach(Plot::fullyResetPlot);
plotsToClear.clear();
}
public boolean isPlotsCleared() {
return plotsToClear.isEmpty();
}
public void resetPlotsGradually() {
if(isPlotsCleared()) {
return;
}
plotsToClear.remove(0).fullyResetPlot();
}
public void addBuildPlot(Plot buildPlot) {
public void teleportToPlots() {
for(Plot buildPlot : plots) {
if(!buildPlot.getMembers().isEmpty()) {
Cuboid cuboid = buildPlot.getCuboid();
if(cuboid == null) {
continue;
}
plots.add(buildPlot);
final Location tploc = cuboid.getCenter();
if(tploc == null) {
continue;
}
if(Version.isCurrentEqualOrLower(Version.v1_13_R2)) { // Async catch in old versions
Location loc = tploc;
int m = 0;
while(loc.getBlock().getType() != Material.AIR) {
if(m >= 500) {
break;// Thread never ends on flat map?
}
if(arena.getArenaState() == ArenaState.IN_GAME && arena.getTimer() > 30) {
break;
}
loc = loc.add(0, 1, 0);
//teleporting 1 x and z block away from center cause Y is above plot limit
if(loc.getY() >= cuboid.getMaxPoint().getY()) {
loc = cuboid.getCenter().clone().add(1, 0, 1);
}
m++; // Preventing server froze on flat map
}
for(Player p : buildPlot.getMembers()) {
p.teleport(cuboid.getCenter());
}
} else {
// Should do this in async thread to do not cause dead for the main thread
CompletableFuture.supplyAsync(() -> {
Location loc = tploc;
while(loc.getBlock().getType() != Material.AIR) {
if(arena.getArenaState() == ArenaState.IN_GAME && arena.getTimer() > 30) {
break; // Thread never ends on flat map?
}
loc = loc.add(0, 1, 0);
//teleporting 1 x and z block away from center cause Y is above plot limit
if(loc.getY() >= cuboid.getMaxPoint().getY()) {
loc = cuboid.getCenter().clone().add(1, 0, 1);
}
}
return loc;
}).thenAccept(loc -> {
for(Player p : buildPlot.getMembers()) {
p.teleport(cuboid.getCenter());
//apply creative again to prevent multiverse default gamemode on world switch
p.setGameMode(GameMode.CREATIVE);
}
});
}
}
Bukkit.getPluginManager().callEvent(new BBPlayerPlotReceiveEvent(arena, buildPlot));
}
}
public List<Plot> getPlots() {
return plots;
}
public void removeBuildPlot(Plot buildPlot) {
plots.remove(buildPlot);
}
public Plot getPlot(Player player) {
if (player != null) {
for (Plot buildPlot : plots) {
if (buildPlot.getMembers().contains(player)) {
return buildPlot;
}
}
}
return null;
}
public void resetQueuedPlots() {
plotsToClear.forEach(Plot::fullyResetPlot);
plotsToClear.clear();
}
public boolean isPlotsCleared() {
return plotsToClear.isEmpty();
}
public void resetPlotsGradually() {
if (isPlotsCleared()) {
return;
}
plotsToClear.remove(0).fullyResetPlot();
}
public void teleportToPlots() {
for (Plot buildPlot : plots) {
if (!buildPlot.getMembers().isEmpty()) {
Cuboid cuboid = buildPlot.getCuboid();
if (cuboid == null) {
continue;
}
final Location tploc = cuboid.getCenter();
if (tploc == null) {
continue;
}
// Block reads stay on the main thread; the walk is bounded by the plot height.
Location loc = tploc;
int maxSteps = Math.max(1, cuboid.getMaxPoint().getBlockY() - cuboid.getMinPoint().getBlockY() + 2);
for (int step = 0; step < maxSteps && loc.getBlock().getType() != Material.AIR; step++) {
loc = loc.add(0, 1, 0);
// teleporting 1 x and z block away from center cause Y is above plot limit
if (loc.getY() >= cuboid.getMaxPoint().getY()) {
loc = cuboid.getCenter().clone().add(1, 0, 1);
}
}
for (Player player : buildPlot.getMembers()) {
VersionUtils.teleport(player, loc);
// Fix respawning bug while theme voting
Bukkit.getScheduler().runTaskLater(arena.getPlugin(), () -> {
player.setAllowFlight(true);
player.setFlying(true);
}, 2);
}
}
Bukkit.getPluginManager().callEvent(new PlotPlayerReceiveEvent(arena, buildPlot));
}
}
public List<Plot> getTopPlotsOrder() {
List<Plot> plotRanking = plots.stream().filter(plot -> !plot.getMembers().isEmpty())
.sorted(Comparator.comparingInt(Plot::getPoints)).collect(Collectors.toList());
Collections.reverse(plotRanking);
return plotRanking;
}
public List<Plot> getPlots() {
return plots;
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,24 +22,19 @@ package plugily.projects.buildbattle.arena.managers.plots;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.api.event.plot.BBPlayerChoosePlotEvent;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.handlers.items.SpecialItem;
import plugily.projects.buildbattle.handlers.items.SpecialItemsManager;
import plugily.projects.buildbattle.utils.Utils;
import plugily.projects.commonsbox.minecraft.compat.VersionUtils;
import plugily.projects.commonsbox.minecraft.compat.xseries.XMaterial;
import plugily.projects.commonsbox.minecraft.item.ItemBuilder;
import plugily.projects.inventoryframework.gui.GuiItem;
import plugily.projects.inventoryframework.gui.type.ChestGui;
import plugily.projects.inventoryframework.pane.StaticPane;
import plugily.projects.buildbattle.api.event.plot.PlotPlayerChooseEvent;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.minigamesbox.classic.handlers.items.SpecialItem;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
import plugily.projects.minigamesbox.classic.utils.items.HandlerItem;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.minigamesbox.inventory.utils.fastinv.InventoryScheme;
import plugily.projects.minigamesbox.inventory.utils.fastinv.PaginatedFastInv;
import java.util.ArrayList;
import java.util.List;
@@ -48,120 +43,163 @@ import java.util.List;
* Created by Tigerpanzer_02 on 26/Jul/2021.
*/
public class PlotMenuHandler implements Listener {
public final class PlotMenuHandler {
private final Main plugin;
private final ItemStack empty;
private final ItemStack waiting;
private final ItemStack full;
private final ItemStack inside;
private final String fullTeam;
private final String emptyTeam;
private final String insideTeam;
private final String teamName;
private final SpecialItem baseItem;
private final Main plugin;
private final ItemStack empty;
private final ItemStack waiting;
private final ItemStack full;
private final ItemStack inside;
private final SpecialItem baseItem;
public PlotMenuHandler(Main plugin) {
this.plugin = plugin;
this.baseItem = plugin.getSpecialItemsManager().getSpecialItem(SpecialItemsManager.SpecialItems.PLOT_SELECTOR.getName());
empty = XMaterial.GREEN_WOOL.parseItem();
waiting = XMaterial.YELLOW_WOOL.parseItem();
full = XMaterial.RED_WOOL.parseItem();
inside = XMaterial.PINK_WOOL.parseItem();
fullTeam = plugin.getChatManager().colorMessage("Plots.Team.Full");
emptyTeam = plugin.getChatManager().colorMessage("Plots.Team.Empty");
insideTeam = plugin.getChatManager().colorMessage("Plots.Team.Inside");
teamName = plugin.getChatManager().colorMessage("Plots.Team.Name");
public PlotMenuHandler(Main plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
this.plugin = plugin;
this.baseItem = plugin.getSpecialItemManager().getSpecialItem("PLOT_SELECTOR");
private ItemStack getItemStack(Plot plot, int maxPlotMembers, Player player) {
int plotMembers = plot.getMembers().size();
empty = XMaterial.GREEN_WOOL.parseItem();
waiting = XMaterial.YELLOW_WOOL.parseItem();
full = XMaterial.RED_WOOL.parseItem();
inside = XMaterial.PINK_WOOL.parseItem();
if(plotMembers == 0) {
return empty.clone();
}
if(plot.getMembers().contains(player)) {
return inside.clone();
}
private ItemStack getItemStack(Plot plot, int maxPlotMembers, Player player) {
if(plotMembers == maxPlotMembers) {
return full.clone();
}
if (plot.getMembers().isEmpty()) {
return waiting.clone();
}
return empty.clone();
public void createMenu(Player player, BaseArena arena) {
ChestGui gui = new ChestGui(Utils.serializeInt(arena.getPlotManager().getPlots().size()) / 9, plugin.getChatManager().colorMessage("Plots.Team.Menu-Name"));
StaticPane pane = new StaticPane(9, gui.getRows());
gui.addPane(pane);
int x = 0;
int y = 0;
int plots = 0;
for(Plot plot : arena.getPlotManager().getPlots()) {
ItemStack itemStack = getItemStack(plot, arena.getPlotSize(), player);
itemStack.setAmount(plot.getMembers().size() == 0 ? 1 : plot.getMembers().size());
if(plot.getMembers().size() >= arena.getPlotSize()) {
itemStack = new ItemBuilder(itemStack).lore(fullTeam).build();
} else {
itemStack = new ItemBuilder(itemStack).lore(emptyTeam).build();
}
if(plot.getMembers().size() > 0) {
List<String> players = new ArrayList<>();
for(Player inside : plot.getMembers()) {
players.add("- " + inside.getName());
}
itemStack = new ItemBuilder(itemStack).lore(players).build();
}
if(plot.getMembers().contains(player)) {
itemStack = new ItemBuilder(itemStack).lore(insideTeam).build();
}
itemStack = new ItemBuilder(itemStack).name(teamName.replace("%plot%", Integer.toString(plots))).build();
int finalPlots = plots;
pane.addItem(new GuiItem(itemStack, e -> {
e.setCancelled(true);
if(!(e.getWhoClicked() instanceof Player) || !(e.isLeftClick() || e.isRightClick())) {
return;
}
BBPlayerChoosePlotEvent event = new BBPlayerChoosePlotEvent(player, plot, arena);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
return;
}
if(!plot.addMember(player, arena, false)) {
return;
}
player.sendMessage(plugin.getChatManager().colorMessage("Plots.Team.Plot-Choose").replace("%plot%", Integer.toString(finalPlots)));
e.getWhoClicked().closeInventory();
}), x, y);
plots++;
x++;
if(x == 9) {
x = 0;
y++;
}
}
gui.show(player);
}
@EventHandler
public void onPlotMenuItemClick(PlayerInteractEvent e) {
if(!(e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)) {
return;
if (plot.getMembers().contains(player)) {
return inside.clone();
}
if (plot.getMembersSize() == maxPlotMembers) {
return full.clone();
}
return waiting.clone();
}
ItemStack stack = VersionUtils.getItemInHand(e.getPlayer());
if(!stack.equals(baseItem.getItemStack())) {
return;
public void createMenu(Player player, BaseArena arena) {
PaginatedFastInv gui = new PaginatedFastInv(27,
new MessageBuilder("IN_GAME_MESSAGES_PLOT_SELECTOR_MENU_NAME").asKey().build());
new InventoryScheme().mask(" 1111111 ").mask(" 1111111 ").bindPagination('1').apply(gui);
int plots = 0;
int arenaPlotMemberSize = arena.getArenaOption("PLOT_MEMBER_SIZE");
gui.previousPageItem(20,
p -> new ItemBuilder(XMaterial.ARROW.parseItem()).name("<- " + p + "/" + gui.lastPage()).build());
gui.nextPageItem(24,
p -> new ItemBuilder(XMaterial.ARROW.parseItem()).name(p + "/" + gui.lastPage() + " ->").build());
gui.setItem(22, new ItemBuilder(XMaterial.BARRIER.parseItem()).name("X").build(),
e -> e.getWhoClicked().closeInventory());
for (Plot plot : arena.getPlotManager().getPlots()) {
ItemStack itemStack = getItemStack(plot, arenaPlotMemberSize, player);
int plotMemberSize = plot.getMembersSize();
itemStack.setAmount(plotMemberSize == 0 ? 1 : plotMemberSize);
itemStack = new ItemBuilder(itemStack).lore(
new MessageBuilder(plotMemberSize >= arenaPlotMemberSize ? "IN_GAME_MESSAGES_PLOT_SELECTOR_FULL"
: "IN_GAME_MESSAGES_PLOT_SELECTOR_EMPTY").asKey().build())
.build();
if (plotMemberSize != 0) {
List<String> players = new ArrayList<>(plotMemberSize);
for (Player plotMember : plot.getMembers()) {
players.add("- " + plotMember.getName());
}
itemStack = new ItemBuilder(itemStack).lore(players).build();
}
if (plot.getMembers().contains(player)) {
itemStack = new ItemBuilder(itemStack)
.lore(new MessageBuilder("IN_GAME_MESSAGES_PLOT_SELECTOR_INSIDE").asKey().build()).build();
}
itemStack = new ItemBuilder(itemStack)
.name(new MessageBuilder("IN_GAME_MESSAGES_PLOT_SELECTOR_NAME").asKey().integer(plots).build())
.build();
new HandlerItem(itemStack).addInteractHandler(event -> {
if (!(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)) {
return;
}
if (!VersionUtils.getItemInHand(event.getPlayer()).equals(baseItem.getItemStack())) {
return;
}
BaseArena baseArena = plugin.getArenaRegistry().getArena(event.getPlayer());
if (baseArena == null) {
return;
}
event.setCancelled(true);
createMenu(event.getPlayer(), baseArena);
});
int finalPlots = plots;
gui.addContent(itemStack, event -> {
event.setCancelled(true);
if (!(event.isLeftClick() || event.isRightClick())) {
return;
}
PlotPlayerChooseEvent plotChooseEvent = new PlotPlayerChooseEvent(player, plot, arena);
Bukkit.getPluginManager().callEvent(plotChooseEvent);
if (plotChooseEvent.isCancelled() || !plot.addMember(player, arena, false)) {
return;
}
new MessageBuilder("IN_GAME_MESSAGES_PLOT_SELECTOR_PLOT_CHOOSE").asKey().player(player)
.integer(finalPlots).sendPlayer();
event.getWhoClicked().closeInventory();
});
plots++;
}
gui.open(player);
}
BaseArena arena = ArenaRegistry.getArena(e.getPlayer());
if(arena == null) {
return;
}
e.setCancelled(true);
createMenu(e.getPlayer(), arena);
}
}
@@ -1,58 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.options;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public enum ArenaOption {
/**
* Current arena timer, ex. 30 seconds before game starts.
*/
TIMER(0),
/**
* Minimum players in arena needed to start.
*/
MINIMUM_PLAYERS(2),
/**
* Maximum players arena can hold, users with full games permission can bypass this!
*/
MAXIMUM_PLAYERS(10),
/**
* Value for checking whether player is in plot or not, otherwise teleport him back.
* <p>
* Each time values reach 1 check will be run.
*/
IN_PLOT_CHECKER(0);
private final int defaultValue;
ArenaOption(int defaultValue) {
this.defaultValue = defaultValue;
}
public int getDefaultValue() {
return defaultValue;
}
}
@@ -0,0 +1,481 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.states.build;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.arena.vote.VoteItems;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.states.PluginInGameState;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author Tigerpanzer_02
* <p>
* Created at 28.05.2022
*/
public class InGameState extends PluginInGameState {
@Override
public void handleCall(PluginArena arena) {
super.handleCall(arena);
BuildArena pluginArena = (BuildArena) getPlugin().getArenaRegistry().getArena(arena.getId());
if (pluginArena == null) {
return;
}
switch (pluginArena.getArenaInGameState()) {
case THEME_VOTING:
if (pluginArena.isRandomTheme() && pluginArena.getTheme() == null) {
pluginArena.setTheme(pluginArena.pickRandomTheme());
}
if (arena.getTimer() <= 0 || pluginArena.getTheme() != null) {
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.BUILD_TIME);
setArenaTimer(getPlugin().getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".In-Game"));
if (pluginArena.getVotePoll() != null && pluginArena.getTheme() == null) {
pluginArena.setTheme(pluginArena.getVotePoll().getVotedTheme());
}
if (pluginArena.getTheme() != null) {
pluginArena.getPlayedThemes().add(pluginArena.getTheme());
}
new MessageBuilder("IN_GAME_MESSAGES_PLOT_ROUND_START").asKey().arena(pluginArena).sendArena();
new TitleBuilder("IN_GAME_MESSAGES_PLOT_ROUND_TITLE").asKey().arena(pluginArena).sendArena();
for (Player player : pluginArena.getPlayersLeft()) {
player.closeInventory();
pluginArena.getPlugin().getBuilderCreativeManager().grantBuilderCreative(player);
VersionUtils.setCollidable(player, false);
}
// second time after voting as sometimes world switch causing no teleportation!
pluginArena.getPlotManager().teleportToPlots();
} else {
handleThemeVoting(pluginArena);
}
break;
case BUILD_TIME:
handleBuildTime(pluginArena);
handleOptionsMenu(pluginArena);
if (arena.getTimer() <= 0) {
for (Player player : pluginArena.getPlayersLeft()) {
IUser user = getPlugin().getUserManager().getUser(player);
Plot playerPlot = pluginArena.getPlotFromPlayer(player);
if (!pluginArena.getQueue().contains(playerPlot)) {
pluginArena.getQueue().add(playerPlot);
}
player.getInventory().clear();
pluginArena.getPlugin().getVoteItems().giveVoteItems(player);
user.setStatistic("LOCAL_POINTS", 3);
}
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.PLOT_VOTING);
voteForNextPlot(pluginArena);
}
break;
case PLOT_VOTING:
handlePlotVoting(pluginArena);
if (arena.getTimer() <= 0) {
calculatePlotResults(pluginArena);
if (pluginArena.getQueue().isEmpty() && !pluginArena.isLastRound()) {
startNextRound(pluginArena);
} else if (pluginArena.getQueue().isEmpty()) {
pluginArena.calculateWinnerPlot();
adjustStatistics(pluginArena);
pluginArena.teleportToWinnerPlot();
getPlugin().getArenaManager().stopGame(false, arena);
pluginArena.executeEndRewards();
} else {
voteForNextPlot(pluginArena);
}
}
break;
default:
break;
}
// no players - stop game
if (!pluginArena.enoughPlayersToContinue()) {
getPlugin().getArenaManager().stopGame(true, pluginArena);
}
}
private void calculatePlotResults(BuildArena pluginArena) {
Plot votingPlot = pluginArena.getVotingPlot();
if (votingPlot == null || votingPlot.getRoundPoints() != 0) {
return;
}
boolean hidePlotOwner = getPlugin().getConfigPreferences().getOption("PLOT_HIDE_OWNER");
String formattedMembers = "";
if (hidePlotOwner) {
formattedMembers = votingPlot.getFormattedMembers();
}
List<Plot> plotsVoted = new ArrayList<>();
for (Player player : pluginArena.getPlayersLeft()) {
if (hidePlotOwner) {
new MessageBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_WAS").asKey().arena(pluginArena)
.player(player).value(formattedMembers).sendArena();
new TitleBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_TITLE").asKey().arena(pluginArena)
.player(player).value(formattedMembers).sendArena();
}
IUser user = getPlugin().getUserManager().getUser(player);
int points = user.getStatistic("LOCAL_POINTS");
// no vote made, in this case make it a good vote
if (points == 0) {
points = 3;
}
Plot plot = pluginArena.getPlotFromPlayer(player);
if (!votingPlot.getMembers().contains(player)) {
if (!plotsVoted.contains(plot)) {
votingPlot.addPoints(points);
plotsVoted.add(plot);
}
}
user.setStatistic("LOCAL_POINTS", 3);
}
}
private void adjustStatistics(BuildArena pluginArena) {
for (Plot plot : pluginArena.getPlotManager().getTopPlotsOrder()) {
plot.getMembers().forEach(player -> {
IUser user = getPlugin().getUserManager().getUser(player);
if (plot.getPoints() > user.getStatistic("POINTS_HIGHEST")) {
user.setStatistic("POINTS_HIGHEST", plot.getPoints());
}
user.adjustStatistic("POINTS_TOTAL", plot.getPoints());
if (plot == pluginArena.getWinnerPlot()) {
user.adjustStatistic("WINS", 1);
} else {
user.adjustStatistic("LOSES", 1);
}
getPlugin().getUserManager().addExperience(player, 5);
if (plot.getPoints() > user.getStatistic("POINTS_HIGHEST_WIN")) {
user.setStatistic("POINTS_HIGHEST_WIN", plot.getPoints());
}
});
}
}
// Judging is over but rounds remain: wipe the plots and send everyone home.
private void startNextRound(BuildArena pluginArena) {
pluginArena.nextRound();
for (Player player : pluginArena.getPlayersLeft()) {
// Vote items would otherwise become building blocks in creative.
player.getInventory().clear();
player.closeInventory();
}
Location spectatorLoc = pluginArena.getSpectatorLocation();
if (spectatorLoc != null) {
for (Player spectator : pluginArena.getSpectators()) {
VersionUtils.teleport(spectator, spectatorLoc);
}
}
pluginArena.getPlotManager().teleportToPlots();
setArenaTimer(getPlugin().getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".Voting.Theme"));
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.THEME_VOTING);
}
private void handleThemeVoting(BuildArena pluginArena) {
for (Player player : pluginArena.getPlayersLeft()) {
pluginArena.getVoteMenu().updateInventory(player);
}
}
private void handleBuildTime(BuildArena pluginArena) {
int timer = pluginArena.getTimer();
for (int timers : getPlugin().getConfig().getIntegerList("Time-Manager.Time-Left-Intervals")) {
if (timers == timer) {
pluginArena.sendBuildLeftTimeMessage();
break;
}
}
pluginArena.checkPlayerOutSidePlot();
}
private void handleOptionsMenu(BuildArena pluginArena) {
if (pluginArena.getTimer() % 10 != 0) {
return;
}
for (Player player : pluginArena.getPlayersLeft()) {
pluginArena.getPlugin().getSpecialItemManager().getSpecialItem("OPTIONS_MENU").setItem(player);
}
}
private void handlePlotVoting(BuildArena pluginArena) {
}
public void voteForNextPlot(BuildArena pluginArena) {
Plot votingPlot = pluginArena.getVotingPlot();
if (votingPlot != null) {
if (votingPlot.getRoundPoints() == 0) {
List<Plot> plotsVoted = new ArrayList<>();
for (Player player : pluginArena.getPlayersLeft()) {
IUser user = getPlugin().getUserManager().getUser(player);
Plot plot = pluginArena.getPlotFromPlayer(player);
if (!votingPlot.getMembers().contains(player)) {
if (!plotsVoted.contains(plot)) {
votingPlot.addPoints(user.getStatistic("LOCAL_POINTS"));
plotsVoted.add(plot);
}
}
user.setStatistic("LOCAL_POINTS", 3);
VoteItems voteItems = pluginArena.getPlugin().getVoteItems();
if (!player.getInventory().contains(voteItems.getReportItem())) {
player.getInventory().setItem(voteItems.getReportVoteItem().getSlot(),
voteItems.getReportVoteItem().getItemStack());
player.updateInventory();
}
}
}
if (!votingPlot.getMembers().isEmpty() && getPlugin().getConfigPreferences().getOption("PLOT_HIDE_OWNER")) {
String formattedMembers = votingPlot.getFormattedMembers();
new MessageBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_WAS").asKey().arena(pluginArena)
.value(formattedMembers).sendArena();
new TitleBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_TITLE").asKey().arena(pluginArena)
.value(formattedMembers).sendArena();
}
}
voteRoutine(pluginArena);
}
public void voteRoutine(BuildArena pluginArena) {
if (pluginArena.getQueue().isEmpty()) {
return;
}
setArenaTimer(getPlugin().getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".Voting.Plot"));
Plot plot = pluginArena.getQueue().poll();
while (plot == null && !pluginArena.getQueue().isEmpty()) {
// should not happen anymore... to be removed
getPlugin().getDebugger().debug("A PLAYER HAS NO PLOT!");
plot = pluginArena.getQueue().poll();
}
if (pluginArena.getQueue().isEmpty() && plot == null) {
pluginArena.setVotingPlot(null);
return;
}
pluginArena.setVotingPlot(plot);
if (plot == null) {
return;
}
Location teleportLoc = plot.getTeleportLocation();
String formattedMembers = plot.getFormattedMembers();
boolean hidePlotOwner = getPlugin().getConfigPreferences().getOption("PLOT_HIDE_OWNER");
for (Player player : pluginArena.getPlayersLeft()) {
VersionUtils.teleport(player, teleportLoc);
player.setPlayerWeather(plot.getWeatherType());
player.setPlayerTime(Plot.Time.format(plot.getTime(), player.getWorld().getTime()), false);
if (hidePlotOwner) {
new MessageBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_NEXT").asKey().arena(pluginArena)
.value("???").player(player).sendPlayer();
} else {
new TitleBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_TITLE").asKey().arena(pluginArena)
.value(formattedMembers).player(player).sendPlayer();
new MessageBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_NEXT").asKey().arena(pluginArena)
.value(formattedMembers).player(player).sendPlayer();
}
}
for (Player spectator : pluginArena.getSpectators()) {
VersionUtils.teleport(spectator, teleportLoc);
spectator.setPlayerWeather(plot.getWeatherType());
spectator.setPlayerTime(Plot.Time.format(plot.getTime(), spectator.getWorld().getTime()), false);
new TitleBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_TITLE").asKey().arena(pluginArena)
.value(formattedMembers).player(spectator).sendPlayer();
new MessageBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_NEXT").asKey().arena(pluginArena)
.value(formattedMembers).player(spectator).sendPlayer();
}
}
}
@@ -0,0 +1,67 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.states.build;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.handlers.menu.registry.particles.ParticleRefreshScheduler;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.states.PluginStartingState;
/**
* @author Plajer
* <p>
* Created at 03.06.2019
*/
public class StartingState extends PluginStartingState {
@Override
public void handleCall(PluginArena arena) {
super.handleCall(arena);
BuildArena pluginArena = (BuildArena) getPlugin().getArenaRegistry().getArena(arena.getId());
if (pluginArena == null) {
return;
}
if (arena.getTimer() == 0 || arena.isForceStart()) {
pluginArena.setParticleRefreshScheduler(new ParticleRefreshScheduler(getPlugin()));
if (!pluginArena.getPlotManager().isPlotsCleared()) {
pluginArena.getPlotManager().resetQueuedPlots();
}
pluginArena.distributePlots();
setArenaTimer(getPlugin().getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".Voting.Theme"));
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.THEME_VOTING);
}
}
}
@@ -0,0 +1,489 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.states.guess;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.GuessArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.handlers.themes.GuessTheme;
import plugily.projects.buildbattle.handlers.themes.ThemeManager;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.PluginArenaUtils;
import plugily.projects.minigamesbox.classic.arena.states.PluginInGameState;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.utils.actionbar.ActionBar;
import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.inventory.common.item.SimpleClickableItem;
import plugily.projects.minigamesbox.inventory.normal.NormalFastInv;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
/**
* @author Tigerpanzer_02
* <p>
* Created at 28.05.2022
*/
public class InGameState extends PluginInGameState {
@Override
public void handleCall(PluginArena arena) {
super.handleCall(arena);
GuessArena pluginArena = (GuessArena) getPlugin().getArenaRegistry().getArena(arena.getId());
if (pluginArena == null) {
return;
}
switch (pluginArena.getArenaInGameState()) {
case THEME_VOTING:
if (pluginArena.getBuildPlot() == null) {
pluginArena.setNextPlot();
new TitleBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_BEING_SELECTED").asKey().arena(pluginArena)
.sendArena();
openThemeSelectionInventoryToCurrentBuilder(pluginArena);
break;
}
if (arena.getTimer() <= 0 || pluginArena.isCurrentThemeSet()) {
forceSetTheme(pluginArena);
new MessageBuilder("IN_GAME_MESSAGES_PLOT_GTB_ROUND").asKey().integer(pluginArena.getRound())
.arena(pluginArena).sendArena();
new TitleBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESS_TITLE").asKey().arena(pluginArena)
.sendArena();
Bukkit.getScheduler().runTaskLater(getPlugin(),
() -> pluginArena.getCurrentBuilders().forEach(player ->
{
pluginArena.getPlugin().getBuilderCreativeManager().grantBuilderCreative(player);
pluginArena.getPlayersLeft().forEach(
ingamePlayer -> VersionUtils.hidePlayer(getPlugin(), player, ingamePlayer));
pluginArena.getPlugin().getSpecialItemManager().getSpecialItem("OPTIONS_MENU")
.setItem(player);
}), 40);
setArenaTimer(getPlugin().getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".In-Game"));
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.BUILD_TIME);
break;
}
break;
case BUILD_TIME:
// check not needed anymore
// if(pluginArena.isCurrentThemeSet()) {
int timer = arena.getTimer();
if (timer <= 90) {
if (timer == 90) {
new MessageBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_CHARS").asKey().arena(pluginArena)
.integer(pluginArena.getCurrentBBTheme().getDefaultTheme().length()).sendArena();
}
sendThemeHints(arena, pluginArena);
}
if (timer <= 0) {
// not all guessed
new MessageBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_WAS").asKey()
.value(pluginArena.getCurrentBBTheme().getThemesAsString()).arena(pluginArena).sendArena();
new TitleBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_TITLE").asKey()
.value(pluginArena.getCurrentBBTheme().getThemesAsString()).arena(pluginArena).sendArena();
setArenaTimer(getPlugin().getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".Round-Delay"));
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.PLOT_VOTING);
}
// }
handleBuildTime(pluginArena);
handleOptionsMenu(pluginArena);
break;
case PLOT_VOTING:
for (Player player : pluginArena.getPlayersLeft()) {
PluginArenaUtils.showPlayer(player, arena);
}
if (pluginArena.getRound() + 1 > pluginArena.getPlotList().size()
* pluginArena.getArenaOption("GTB_ROUNDS_PER_PLOT"))
{
pluginArena.calculateWinnerPlot();
adjustStatistics(pluginArena);
pluginArena.teleportToWinnerPlot(); // todo save built plot from winner
pluginArena.executeEndRewards();
getPlugin().getArenaManager().stopGame(false, arena);
} else if (arena.getTimer() <= 0) {
pluginArena.resetBuildPlot();
setArenaTimer(getPlugin().getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".Voting.Theme"));
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.THEME_VOTING);
}
break;
default:
break;
}
// no players - stop game
if (!pluginArena.enoughPlayersToContinue()) {
getPlugin().getArenaManager().stopGame(true, pluginArena);
}
}
private void sendThemeHints(PluginArena arena, GuessArena pluginArena) {
for (Player player : arena.getPlayers()) {
if (pluginArena.getCurrentBuilders().contains(player)) {
continue;
}
if (pluginArena.getWhoGuessed().contains(player)) {
getPlugin().getActionBarManager().addActionBar(player,
new ActionBar(new MessageBuilder(pluginArena.getCurrentBBTheme().getDefaultTheme()),
ActionBar.ActionBarType.DISPLAY));
continue;
}
int themeLength = pluginArena.getCurrentBBTheme().getDefaultTheme().length();
List<Integer> charsAt = new ArrayList<>(themeLength);
for (int i = 0; i < themeLength; i++) {
if (!pluginArena.getRemovedCharsAt().contains(i)) {
charsAt.add(i);
}
}
if (themeLength - pluginArena.getRemovedCharsAt().size() > 2) {
int timer = arena.getTimer();
if (timer % 10 == 0 && timer <= 70) {
pluginArena.getRemovedCharsAt().add(charsAt.get(
charsAt.size() == 1 ? 0 : pluginArena.getPlugin().getRandom().nextInt(charsAt.size())));
continue;
}
}
StringBuilder actionbar = new StringBuilder();
for (int i = 0; i < themeLength; i++) {
char charAt = pluginArena.getCurrentBBTheme().getDefaultTheme().charAt(i);
if (Character.isWhitespace(charAt)) {
actionbar.append(" ");
continue;
}
if (pluginArena.getRemovedCharsAt().contains(i)) {
actionbar.append(charAt).append(' ');
continue;
}
actionbar.append("_ ");
}
getPlugin().getActionBarManager().addActionBar(player,
new ActionBar(new MessageBuilder(actionbar.toString()), ActionBar.ActionBarType.DISPLAY));
}
}
private void forceSetTheme(GuessArena pluginArena) {
if (pluginArena.isCurrentThemeSet()) {
return;
}
GuessTheme.Difficulty difficulty = GuessTheme.Difficulty.EASY;
switch (pluginArena.getPlugin().getRandom().nextInt(2 + 1)) {
case 1:
difficulty = GuessTheme.Difficulty.MEDIUM;
break;
case 2:
difficulty = GuessTheme.Difficulty.HARD;
break;
default:
break;
}
setChosenTheme(pluginArena, getThemeByDifficulty(pluginArena, difficulty));
}
private void handleOptionsMenu(GuessArena pluginArena) {
if (pluginArena.getTimer() % 10 != 0) {
return;
}
for (Player player : pluginArena.getCurrentBuilders()) {
pluginArena.getPlugin().getSpecialItemManager().getSpecialItem("OPTIONS_MENU").setItem(player);
}
}
private void setChosenTheme(GuessArena pluginArena, GuessTheme guessTheme) {
setTheme(pluginArena, guessTheme);
pluginArena.getCurrentBuilders().forEach(HumanEntity::closeInventory);
pluginArena.getCurrentBuilders()
.forEach(
player -> getPlugin().getActionBarManager()
.addActionBar(player,
new ActionBar(
new MessageBuilder("IN_GAME_MESSAGES_PLOT_GTB_THEME_NAME").asKey()
.player(player).arena(pluginArena),
ActionBar.ActionBarType.DISPLAY)));
}
private void openThemeSelectionInventoryToCurrentBuilder(GuessArena pluginArena) {
if (pluginArena.getCurrentBuilders().isEmpty()) {
return;
}
pluginArena.getCurrentBuilders().forEach(HumanEntity::closeInventory);
NormalFastInv gui = new NormalFastInv(9 * 3, new MessageBuilder("MENU_THEME_GTB_INVENTORY").asKey().build());
gui.addClickHandler(inventoryClickEvent -> inventoryClickEvent.setCancelled(true));
gui.addCloseHandler(event -> {
if (!pluginArena.isCurrentThemeSet()) {
Bukkit.getScheduler().runTask(getPlugin(), () -> event.getPlayer().openInventory(event.getInventory()));
}
});
GuessTheme easy = getThemeByDifficulty(pluginArena, GuessTheme.Difficulty.EASY);
gui.setItem(11,
new SimpleClickableItem(
new ItemBuilder(Material.PAPER)
.name(getThemeItemName(pluginArena).value(easy.getThemesAsString()).build())
.lore(getThemeItemLore(pluginArena)
.value(new MessageBuilder("MENU_THEME_GTB_DIFFICULTIES_EASY").asKey().build())
.integer(easy.getDifficulty().getPointsReward()).build().split(";"))
.build(),
event ->
{
setChosenTheme(pluginArena, easy);
}));
GuessTheme medium = getThemeByDifficulty(pluginArena, GuessTheme.Difficulty.MEDIUM);
gui.setItem(13,
new SimpleClickableItem(
new ItemBuilder(Material.PAPER)
.name(getThemeItemName(pluginArena).value(medium.getThemesAsString()).build())
.lore(getThemeItemLore(pluginArena)
.value(new MessageBuilder("MENU_THEME_GTB_DIFFICULTIES_MEDIUM").asKey().build())
.integer(medium.getDifficulty().getPointsReward()).build().split(";"))
.build(),
event ->
{
setChosenTheme(pluginArena, medium);
}));
GuessTheme hard = getThemeByDifficulty(pluginArena, GuessTheme.Difficulty.HARD);
gui.setItem(15,
new SimpleClickableItem(
new ItemBuilder(Material.PAPER)
.name(getThemeItemName(pluginArena).value(hard.getThemesAsString()).build())
.lore(getThemeItemLore(pluginArena)
.value(new MessageBuilder("MENU_THEME_GTB_DIFFICULTIES_HARD").asKey().build())
.integer(hard.getDifficulty().getPointsReward()).build().split(";"))
.build(),
event ->
{
setChosenTheme(pluginArena, hard);
}));
getPlugin().getDebugger().debug("Opened Theme Selector for {0}", pluginArena.getCurrentBuilders().toString());
pluginArena.getCurrentBuilders().forEach(gui::open);
}
public MessageBuilder getThemeItemName(GuessArena pluginArena) {
return new MessageBuilder("MENU_THEME_GTB_ITEM_NAME").asKey().arena(pluginArena);
}
public MessageBuilder getThemeItemLore(GuessArena pluginArena) {
return new MessageBuilder("MENU_THEME_GTB_ITEM_LORE").asKey().arena(pluginArena);
}
private GuessTheme getThemeByDifficulty(GuessArena pluginArena, GuessTheme.Difficulty difficulty) {
List<String> themes = pluginArena.getPlugin().getThemeManager()
.getThemes(ThemeManager.GameThemes.getByDifficulty(difficulty));
List<String> themesFilter = new ArrayList<>(themes);
themesFilter.removeAll(pluginArena.getPlayedThemes());
if (themesFilter.isEmpty()) {
themesFilter = themes;
}
String unmatchedThemes = themesFilter.get(getPlugin().getRandom().nextInt(themesFilter.size()));
ArrayList<String> themeNames = new ArrayList<>(Arrays.asList(unmatchedThemes.split("\\s*,\\s*")));
if (themeNames.isEmpty()) {
pluginArena.getPlugin().getDebugger().debug(Level.WARNING,
"&cThemes.yml broken. Th following line was found " + unmatchedThemes
+ " ! Please remove empty lines!");
}
GuessTheme theme = new GuessTheme(themeNames, difficulty);
pluginArena.getPlayedThemes().add(unmatchedThemes);
return theme;
}
private void setTheme(GuessArena pluginArena, GuessTheme theme) {
pluginArena.setCurrentTheme(theme);
}
private void adjustStatistics(GuessArena pluginArena) {
for (Plot plot : pluginArena.getPlotManager().getTopPlotsOrder()) {
plot.getMembers().forEach(player -> {
IUser user = getPlugin().getUserManager().getUser(player);
/*
* //ToDo GTB stats if(plot.getPoints() > user.getStatistic("POINTS_HIGHEST")) {
* user.setStatistic("POINTS_HIGHEST", plot.getPoints()); }
*/
user.adjustStatistic("POINTS_TOTAL", plot.getPoints());
if (plot == pluginArena.getWinnerPlot()) {
user.adjustStatistic("WINS", 1);
} else {
user.adjustStatistic("LOSES", 1);
}
getPlugin().getUserManager().addExperience(player, 5);
/*
* if(plot.getPoints() > user.getStatistic("POINTS_HIGHEST_WIN")) {
* user.setStatistic("POINTS_HIGHEST_WIN", plot.getPoints()); }
*/
});
}
}
private void handleBuildTime(GuessArena pluginArena) {
int timer = pluginArena.getTimer();
for (int timers : getPlugin().getConfig().getIntegerList("Time-Manager.Time-Left-Intervals")) {
if (timers == timer) {
pluginArena.sendBuildLeftTimeMessage();
break;
}
}
pluginArena.checkPlayerOutSidePlot();
}
}
@@ -0,0 +1,66 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.arena.states.guess;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.GuessArena;
import plugily.projects.buildbattle.handlers.menu.registry.particles.ParticleRefreshScheduler;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.states.PluginStartingState;
/**
* @author Plajer
* <p>
* Created at 03.06.2019
*/
public class StartingState extends PluginStartingState {
@Override
public void handleCall(PluginArena arena) {
super.handleCall(arena);
GuessArena pluginArena = (GuessArena) getPlugin().getArenaRegistry().getArena(arena.getId());
if (pluginArena == null) {
return;
}
if (arena.getTimer() == 0 || arena.isForceStart()) {
pluginArena.setParticleRefreshScheduler(new ParticleRefreshScheduler(getPlugin()));
if (!pluginArena.getPlotManager().isPlotsCleared()) {
pluginArena.getPlotManager().resetQueuedPlots();
}
pluginArena.distributePlots();
setArenaTimer(getPlugin().getConfig()
.getInt("Time-Manager." + pluginArena.getArenaType().getPrefix() + ".Voting.Theme"));
pluginArena.setArenaInGameState(BaseArena.ArenaInGameState.THEME_VOTING);
}
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,86 +23,145 @@ package plugily.projects.buildbattle.arena.vote;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import plugily.projects.commonsbox.minecraft.compat.VersionUtils;
import plugily.projects.commonsbox.minecraft.compat.events.api.CBPlayerInteractEvent;
import plugily.projects.commonsbox.minecraft.item.ItemUtils;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.api.StatsStorage;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.impl.GuessTheBuildArena;
import plugily.projects.buildbattle.arena.impl.SoloArena;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.arena.GuessArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.handlers.reward.Reward;
import plugily.projects.buildbattle.user.User;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.user.IUser;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.misc.complement.ComplementAccessor;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.classic.utils.version.events.api.PlugilyPlayerInteractEvent;
/**
* @author Plajer
* <p>
* Created at 23.12.2018
* <p>
* Created at 23.12.2018
*/
public class VoteEvents implements Listener {
private final Main plugin;
private final Main plugin;
public VoteEvents(Main plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
public VoteEvents(Main plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
@EventHandler
public void onVote(CBPlayerInteractEvent e) {
if(VersionUtils.checkOffHand(e.getHand()) || e.getAction() == Action.LEFT_CLICK_AIR || e.getAction() == Action.LEFT_CLICK_BLOCK || e.getAction() == Action.PHYSICAL) {
return;
}
if(!ItemUtils.isItemStackNamed(e.getItem())) {
return;
@EventHandler
public void onVote(PlugilyPlayerInteractEvent event) {
if (event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK
|| event.getAction() == Action.PHYSICAL)
{
return;
}
if (VersionUtils.checkOffHand(event.getHand())) {
return;
}
BaseArena arena = plugin.getArenaRegistry().getArena(event.getPlayer());
if (arena == null || arena.getArenaState() != IArenaState.IN_GAME || arena instanceof GuessArena) {
return;
}
BuildArena solo = (BuildArena) arena;
if (solo.getArenaInGameState() != BaseArena.ArenaInGameState.PLOT_VOTING) {
return;
}
Plot plot = solo.getVotingPlot();
if (plugin.getVoteItems().getReportItem().equals(event.getItem())) {
IUser user = plugin.getUserManager().getUser(event.getPlayer());
user.adjustStatistic("REPORTS_TRIGGERED", 1);
if (plot != null && plugin.getConfigPreferences().getOption("REPORT_COMMANDS")) {
int reportsAmountNeeded = plugin.getConfig().getInt("Report.Amount", -1);
if (reportsAmountNeeded == -1 || user.getStatistic("REPORTS_TRIGGERED") >= reportsAmountNeeded) {
String reportCommand = plugin.getConfig().getString("Report.Execute", "kick %reported%");
reportCommand = reportCommand.replace("%reporter%", event.getPlayer().getName());
for (org.bukkit.entity.Player player : plot.getMembers()) {
plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(),
reportCommand.replace("%reported%", player.getName()));
}
event.getPlayer().getInventory().remove(event.getItem());
event.getPlayer().updateInventory();
plugin.getRewardsHandler().performReward(event.getPlayer(), arena,
plugin.getRewardsHandler().getRewardType("REPORT"));
}
}
event.setCancelled(true);
return;
}
if (plot != null && plot.getMembers().contains(event.getPlayer())) {
new MessageBuilder("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_OWN").asKey().arena(arena)
.player(event.getPlayer()).sendPlayer();
event.setCancelled(true);
return;
}
VoteItems.VoteItem voteItem = plugin.getVoteItems().getVoteItem(event.getItem());
if (voteItem != null) {
plugin.getUserManager().getUser(event.getPlayer()).setStatistic("LOCAL_POINTS",
plugin.getVoteItems().getPointsAndPlayVoteSound(event.getPlayer(), voteItem));
new MessageBuilder("IN_GAME_MESSAGES_PLOT_VOTING_SUCCESS").asKey()
.value(ComplementAccessor.getComplement().getDisplayName(voteItem.getItemStack().getItemMeta()))
.arena(arena).player(event.getPlayer()).sendPlayer();
if (arena.getArenaType() == BaseArena.ArenaType.TEAM) {
plot.getMembers().forEach(player -> {
plugin.getUserManager().getUser(player).setStatistic("LOCAL_POINTS",
plugin.getVoteItems().getPointsAndPlayVoteSound(player, voteItem));
if (player != event.getPlayer()) {
// todo add by who
new MessageBuilder("IN_GAME_MESSAGES_PLOT_VOTING_SUCCESS").asKey()
.value(ComplementAccessor.getComplement()
.getDisplayName(voteItem.getItemStack().getItemMeta()))
.arena(arena).player(event.getPlayer()).send(player);
}
});
}
event.setCancelled(true);
}
}
BaseArena arena = ArenaRegistry.getArena(e.getPlayer());
if(arena == null || arena instanceof GuessTheBuildArena || arena.getArenaState() != ArenaState.IN_GAME) {
return;
}
SoloArena solo = (SoloArena) arena;
if (!solo.isVoting())
return;
User user = plugin.getUserManager().getUser(e.getPlayer());
Plot plot = solo.getVotingPlot();
if(plugin.getVoteItems().getReportItem().equals(e.getItem())) {
user.setStat(StatsStorage.StatisticType.REPORTS, user.getStat(StatsStorage.StatisticType.REPORTS) + 1);
int reportsAmountNeeded = plugin.getConfig().getInt("Run-Command-On-Report.Reports-Amount-To-Run", -1);
if(plot != null && plugin.getConfigPreferences().getOption(ConfigPreferences.Option.RUN_COMMAND_ON_REPORT)
&& (reportsAmountNeeded == -1 || user.getStat(StatsStorage.StatisticType.REPORTS) >= reportsAmountNeeded)) {
plot.getMembers().forEach(player -> plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(),
plugin.getConfig().getString("Run-Command-On-Report.Command", "kick %reported%")
.replace("%reported%", player.getName()).replace("%reporter%", e.getPlayer().getName())));
e.getPlayer().getInventory().remove(e.getItem());
e.getPlayer().updateInventory();
plugin.getRewardsHandler().performReward(e.getPlayer(), Reward.RewardType.REPORT, -1);
}
e.setCancelled(true);
return;
}
if(plot != null && plot.getMembers().contains(e.getPlayer())) {
e.getPlayer().sendMessage(plugin.getChatManager().getPrefix() + plugin.getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Cant-Vote-Own-Plot"));
e.setCancelled(true);
return;
}
user.setStat(StatsStorage.StatisticType.LOCAL_POINTS, plugin.getVoteItems().getPoints(e.getItem()));
plugin.getVoteItems().playVoteSound(e.getPlayer(), e.getItem());
e.getPlayer().sendMessage(plugin.getChatManager().getPrefix() + plugin.getChatManager().colorMessage("In-Game.Messages.Voting-Messages.Vote-Successful"));
e.setCancelled(true);
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,15 +25,13 @@ import org.bukkit.Sound;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Nullable;
import plugily.projects.commonsbox.minecraft.compat.xseries.XMaterial;
import plugily.projects.commonsbox.minecraft.compat.xseries.XSound;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.commonsbox.minecraft.item.ItemBuilder;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.utils.Debugger;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
import java.util.HashSet;
import java.util.Set;
@@ -43,134 +41,232 @@ import java.util.Set;
*/
public class VoteItems {
private final Set<VoteItem> voteItems = new HashSet<>();
private final FileConfiguration config;
private final Main plugin = JavaPlugin.getPlugin(Main.class);
private final Set<VoteItem> voteItems = new HashSet<>();
private final FileConfiguration config;
private final Main plugin;
private ItemStack reportItem = new ItemStack(Material.BEDROCK, 32);
private VoteItem reportVoteItem = new VoteItem(new ItemStack(Material.BEDROCK, 32), 8, 8 + 1, XSound.ENTITY_ARROW_HIT.parseSound());
private ItemStack reportItem = new ItemStack(Material.BEDROCK, 32);
private VoteItem reportVoteItem = new VoteItem(new ItemStack(Material.BEDROCK, 32), 8, 8 + 1,
XSound.ENTITY_ARROW_HIT.parseSound());
public VoteItems() {
config = ConfigUtils.getConfig(plugin, "voteItems");
public VoteItems(Main plugin) {
updateVoteItemsConfig();
loadVoteItems();
}
this.plugin = plugin;
config = ConfigUtils.getConfig(plugin, "vote_items");
private void loadVoteItems() {
for(String key : config.getKeys(false)) {
if(!config.isSet(key + ".displayname")) {
continue;
}
updateVoteItemsConfig();
loadVoteItems();
ItemStack stack = new ItemBuilder(XMaterial.matchXMaterial(config.getString(key + ".material-name", "BEDROCK")
.toUpperCase()).orElse(XMaterial.BEDROCK).parseItem())
.name(plugin.getChatManager().colorRawMessage(config.getString(key + ".displayname")))
.build();
if(config.getBoolean(key + ".report-item-function")) {
reportItem = stack;
}
Sound sound = null;
try {
sound = Sound.valueOf(config.getString(key + ".sound", ""));
} catch(IllegalArgumentException ignored) {
}
int s = Integer.parseInt(key);
VoteItem voteItem = new VoteItem(stack, s, s + 1, sound);
reportVoteItem = voteItem;
voteItems.add(voteItem);
}
}
private void updateVoteItemsConfig() {
for(String key : config.getKeys(false)) {
if(!config.isSet(key + ".displayname") || config.isSet(key + ".material-name")) {
continue;
}
config.set(key + ".material-name", XMaterial.GREEN_TERRACOTTA.name());
Debugger.debug(Debugger.Level.WARN, "Found outdated item in votingItems.yml! We've converted it to the newest version!");
}
ConfigUtils.saveConfig(plugin, config, "voteItems");
}
private void loadVoteItems() {
public void giveVoteItems(Player player) {
for(VoteItem voteItem : voteItems) {
player.getInventory().setItem(voteItem.getSlot(), voteItem.getItemStack());
}
player.updateInventory();
}
for (String key : config.getKeys(false)) {
String displayName = config.getString(key + ".displayname", null);
if (displayName == null) {
continue;
}
ItemStack stack = new ItemBuilder(XMaterial
.matchXMaterial(
config.getString(key + ".material-name", "BEDROCK").toUpperCase(java.util.Locale.ENGLISH))
.orElse(XMaterial.BEDROCK).parseItem()).name(new MessageBuilder(displayName).build()).build();
Sound sound = XSound.matchXSound(config.getString(key + ".sound", "")).orElse(XSound.BLOCK_ANVIL_HIT)
.parseSound();
int slot;
try {
slot = Integer.parseInt(key);
} catch (NumberFormatException e) {
continue;
}
VoteItem voteItem = new VoteItem(stack, slot, slot + 1, sound);
if (config.getBoolean(key + ".report-item-function", false)) {
reportItem = stack;
reportVoteItem = voteItem;
}
voteItems.add(voteItem);
public void playVoteSound(Player player, ItemStack itemStack) {
for(VoteItem item : voteItems) {
if(item.getItemStack().isSimilar(itemStack)) {
if(item.getSound() == null) {
return;
}
player.playSound(player.getLocation(), item.getSound(), 1, 1);
}
}
}
/**
* Get points value of target vote item stack
*
* @param itemStack item stack to get points value from
* @return points
*/
public int getPoints(ItemStack itemStack) {
for(VoteItem item : voteItems) {
if(item.getItemStack().isSimilar(itemStack)) {
return item.getPoints();
}
}
return 1;
}
/**
* @return itemStack that represents report building function
*/
public ItemStack getReportItem() {
return reportItem;
}
/**
* @return itemStack that represents report building function
*/
public VoteItem getReportVoteItem() {
return reportVoteItem;
}
public static class VoteItem {
private final ItemStack itemStack;
private final int slot;
private final int points;
private final Sound sound;
public VoteItem(ItemStack itemStack, int slot, int points, Sound sound) {
this.itemStack = itemStack;
this.slot = slot;
this.points = points;
this.sound = sound;
}
public ItemStack getItemStack() {
return itemStack;
private void updateVoteItemsConfig() {
for (String key : config.getKeys(false)) {
if (!config.isSet(key + ".displayname") || config.isSet(key + ".material-name")) {
continue;
}
config.set(key + ".material-name", XMaterial.GREEN_TERRACOTTA.name());
plugin.getDebugger()
.debug("Found outdated item in vote_items.yml! We've converted it to the newest version!");
}
ConfigUtils.saveConfig(plugin, config, "vote_items");
}
public int getSlot() {
return slot;
public void giveVoteItems(Player player) {
for (VoteItem voteItem : voteItems) {
player.getInventory().setItem(voteItem.slot, voteItem.itemStack);
}
player.updateInventory();
}
public int getPoints() {
return points;
public void playVoteSound(Player player, ItemStack itemStack) {
for (VoteItem item : voteItems) {
if (item.itemStack.isSimilar(itemStack)) {
if (item.sound == null) {
return;
}
player.playSound(player.getLocation(), item.sound, 1, 1);
}
}
}
@Nullable
public Sound getSound() {
return sound;
/**
* Get points value of target vote item stack
*
* @param itemStack item stack to get points value from
* @return points
*/
public int getPoints(ItemStack itemStack) {
for (VoteItem item : voteItems) {
if (item.itemStack.isSimilar(itemStack)) {
return item.points;
}
}
return 1;
}
public int getPointsAndPlayVoteSound(Player player, VoteItem voteItem) {
if (voteItem.sound == null) {
return voteItem.points;
}
player.playSound(player.getLocation(), voteItem.sound, 1, 1);
return voteItem.points;
}
public VoteItem getVoteItem(ItemStack itemStack) {
for (VoteItem item : voteItems) {
if (item.itemStack.isSimilar(itemStack)) {
return item;
}
}
return null;
}
/**
* @return itemStack that represents report building function
*/
public ItemStack getReportItem() {
return reportItem;
}
/**
* @return itemStack that represents report building function
*/
public VoteItem getReportVoteItem() {
return reportVoteItem;
}
public static class VoteItem {
private final ItemStack itemStack;
private final int slot;
private final int points;
private final Sound sound;
public VoteItem(ItemStack itemStack, int slot, int points, Sound sound) {
this.itemStack = itemStack;
this.slot = slot;
this.points = points;
this.sound = sound;
}
public ItemStack getItemStack() {
return itemStack;
}
public int getSlot() {
return slot;
}
public int getPoints() {
return points;
}
@Nullable
public Sound getSound() {
return sound;
}
}
}
}
@@ -0,0 +1,138 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.boot;
import plugily.projects.buildbattle.Main;
import plugily.projects.minigamesbox.api.preferences.IConfigPreferences;
import plugily.projects.minigamesbox.classic.api.StatisticType;
import plugily.projects.minigamesbox.classic.api.StatsStorage;
import plugily.projects.minigamesbox.classic.arena.options.ArenaOption;
import plugily.projects.minigamesbox.classic.arena.options.ArenaOptionManager;
import plugily.projects.minigamesbox.classic.handlers.items.SpecialItemManager;
import plugily.projects.minigamesbox.classic.handlers.permissions.PermissionCategory;
import plugily.projects.minigamesbox.classic.handlers.permissions.PermissionsManager;
import plugily.projects.minigamesbox.classic.handlers.reward.RewardType;
import plugily.projects.minigamesbox.classic.handlers.reward.RewardsFactory;
import plugily.projects.minigamesbox.classic.preferences.ConfigOption;
/**
* @author Tigerpanzer_02
* <p>
* Created at 15.10.2022
*/
public class AdditionalValueInitializer {
private final Main plugin;
public AdditionalValueInitializer(Main plugin) {
this.plugin = plugin;
registerConfigOptions();
registerStatistics();
registerPermission();
registerRewards();
registerSpecialItems();
registerArenaOptions();
}
private void registerConfigOptions() {
IConfigPreferences configPreferences = plugin.getConfigPreferences();
configPreferences.registerOption("MOB_SPAWN", new ConfigOption("Mob.Spawn", false));
configPreferences.registerOption("HEAD_MENU_CUSTOM", new ConfigOption("Head-Menu.Custom", false));
configPreferences.registerOption("REPORT_COMMANDS", new ConfigOption("Report.Commands", false));
configPreferences.registerOption("PLOT_HIDE_OWNER", new ConfigOption("Plot.Hide-Owner", false));
configPreferences.registerOption("PLOT_MOVE_OUTSIDE", new ConfigOption("Plot.Move-Outside", false));
configPreferences.registerOption("SUPER_VOTES", new ConfigOption("Super-Votes", true));
}
private void registerStatistics() {
StatsStorage statsStorage = plugin.getStatsStorage();
statsStorage.registerStatistic("BLOCKS_PLACED",
new StatisticType("blocks_placed", true, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("BLOCKS_BROKEN",
new StatisticType("blocks_broken", true, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("POINTS_HIGHEST",
new StatisticType("points_highest", true, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("POINTS_HIGHEST_WIN",
new StatisticType("points_highest_win", true, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("POINTS_TOTAL",
new StatisticType("points_total", true, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("PARTICLES_USED",
new StatisticType("particles_used", true, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("SUPER_VOTES",
new StatisticType("super_votes", true, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("LOCAL_POINTS",
new StatisticType("local_points", false, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("LOCAL_POINTS_GTB",
new StatisticType("local_points_gtb", false, "int(11) NOT NULL DEFAULT '0'"));
statsStorage.registerStatistic("REPORTS_TRIGGERED",
new StatisticType("reports_triggered", false, "int(11) NOT NULL DEFAULT '0'"));
}
private void registerPermission() {
PermissionsManager permissionsManager = plugin.getPermissionsManager();
permissionsManager.registerPermissionCategory("POINTS_BOOSTER", new PermissionCategory("Points-Boost", null));
permissionsManager.registerPermissionCategory("VOTING_BOOSTER", new PermissionCategory("Voting-Boost", null));
}
private void registerRewards() {
RewardsFactory rewardsFactory = plugin.getRewardsHandler();
rewardsFactory.registerRewardType("GUESS", new RewardType("guessed"));
rewardsFactory.registerRewardType("GUESS_ALL", new RewardType("guessed-all"));
rewardsFactory.registerRewardType("VOTE", new RewardType("voted"));
rewardsFactory.registerRewardType("VOTE_ALL", new RewardType("voted-all"));
rewardsFactory.registerRewardType("REPORT", new RewardType("report"));
rewardsFactory.registerRewardType("PLACE", new RewardType("place", RewardType.ExecutorType.NUMBER, false));
}
private void registerSpecialItems() {
SpecialItemManager specialItemManager = plugin.getSpecialItemManager();
specialItemManager.registerSpecialItem("OPTIONS_MENU", "Options-Menu");
specialItemManager.registerSpecialItem("PLOT_SELECTOR", "Plot-Selector");
}
private void registerArenaOptions() {
ArenaOptionManager arenaOptionManager = plugin.getArenaOptionManager();
arenaOptionManager.registerArenaOption("IN_PLOT_CHECKER", new ArenaOption("null", 0, true));
arenaOptionManager.registerArenaOption("PLOT_MEMBER_SIZE", new ArenaOption("plotmembersize", 1, true));
arenaOptionManager.registerArenaOption("GTB_ROUNDS_PER_PLOT", new ArenaOption("roundsperplot", 2, true));
}
}
@@ -0,0 +1,284 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.boot;
import plugily.projects.buildbattle.Main;
import plugily.projects.minigamesbox.classic.handlers.language.Message;
import plugily.projects.minigamesbox.classic.handlers.language.MessageManager;
/**
* @author Tigerpanzer_02
* <p>
* Created at 15.10.2022
*/
public class MessageInitializer {
private final Main plugin;
public MessageInitializer(Main plugin) {
this.plugin = plugin;
}
public void registerMessages() {
MessageManager messageManager = plugin.getMessageManager();
messageManager.registerMessage("COMMANDS_THEME_BLACKLISTED", new Message("Commands.Theme-Blacklisted", ""));
messageManager.registerMessage("COMMANDS_ADMIN_ADDED_PLOT", new Message("Commands.Admin.Added-Plot", ""));
messageManager.registerMessage("SCOREBOARD_THEME_UNKNOWN", new Message("Scoreboard.Theme-Unknown", ""));
// scoreboard ingame classic/teams/guess-the-build/guess-the-build-waiting |
// ending classic/guess-the-build
messageManager.registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_WINNER",
new Message("In-Game.Messages.Game-End.Placeholders.Winner", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_PLACE",
new Message("In-Game.Messages.Game-End.Placeholders.Place", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_OWN",
new Message("In-Game.Messages.Game-End.Placeholders.Own", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_ADMIN_CHANGED_THEME",
new Message("In-Game.Messages.Admin.Changed-Theme", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_", new Message("In-Game.Messages.Plot.", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_NOBODY", new Message("In-Game.Messages.Plot.Nobody", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_TIME_LEFT_TITLE",
new Message("In-Game.Messages.Plot.Time-Left.Title", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_TIME_LEFT_CHAT",
new Message("In-Game.Messages.Plot.Time-Left.Chat", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_LIMIT_ENTITIES",
new Message("In-Game.Messages.Plot.Limit.Entities", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_LIMIT_PARTICLES",
new Message("In-Game.Messages.Plot.Limit.Particles", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_PERMISSION_HEAD",
new Message("In-Game.Messages.Plot.Permission.Head", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_PERMISSION_PARTICLE",
new Message("In-Game.Messages.Plot.Permission.Particle", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_PERMISSION_BIOME",
new Message("In-Game.Messages.Plot.Permission.Biome", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_PERMISSION_OUTSIDE",
new Message("In-Game.Messages.Plot.Permission.Outside", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_PERMISSION_FLOOR_ITEM",
new Message("In-Game.Messages.Plot.Permission.Floor-Item", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_SELECTOR_FULL",
new Message("In-Game.Messages.Plot.Selector.Full", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_SELECTOR_EMPTY",
new Message("In-Game.Messages.Plot.Selector.Empty", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_SELECTOR_INSIDE",
new Message("In-Game.Messages.Plot.Selector.Inside", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_SELECTOR_NAME",
new Message("In-Game.Messages.Plot.Selector.Name", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_SELECTOR_MENU_NAME",
new Message("In-Game.Messages.Plot.Selector.Menu-Name", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_SELECTOR_PLOT_CHOOSE",
new Message("In-Game.Messages.Plot.Selector.Plot-Choose", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_SELECTOR_MEMBER",
new Message("In-Game.Messages.Plot.Selector.Member", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_VOTING_NAME",
new Message("In-Game.Messages.Plot.Voting.Name", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_CHAT",
new Message("In-Game.Messages.Plot.Voting.Plot-Owner.Chat", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_TITLE",
new Message("In-Game.Messages.Plot.Voting.Plot-Owner.Title", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_NEXT",
new Message("In-Game.Messages.Plot.Voting.Plot-Owner.Next", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_WAS",
new Message("In-Game.Messages.Plot.Voting.Plot-Owner.Was", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_VOTING_PLOT_OWNER_OWN",
new Message("In-Game.Messages.Plot.Voting.Plot-Owner.Own", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_VOTING_SUCCESS",
new Message("In-Game.Messages.Plot.Voting.Success", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_VOTING_WINNER",
new Message("In-Game.Messages.Plot.Voting.Winner", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_ROUND_START",
new Message("In-Game.Messages.Plot.Round.Start", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_ROUND_TITLE",
new Message("In-Game.Messages.Plot.Round.Title", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_BUILDER",
new Message("In-Game.Messages.Plot.Guess-The-Build.Builder", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_ROUND",
new Message("In-Game.Messages.Plot.Guess-The-Build.Round", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_CHARS",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Chars", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_NAME",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Name", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_WAS",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Was", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_TITLE",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Title", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESSED",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Guessed", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_BEING_SELECTED",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Being-Selected", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESS_TITLE",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Guess.Title", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESS_POINTS",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Guess.Points", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESS_GUESSED",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Guess.Guessed", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESS_CANT_TALK",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Guess.Cant-Talk", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_GTB_THEME_GUESS_BUILDER",
new Message("In-Game.Messages.Plot.Guess-The-Build.Theme.Guess.Builder", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_NPC_NAME",
new Message("In-Game.Messages.Plot.NPC.Name", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_NPC_CREATED",
new Message("In-Game.Messages.Plot.NPC.Created", ""));
messageManager.registerMessage("IN_GAME_MESSAGES_PLOT_NPC_CITIZENS",
new Message("In-Game.Messages.Plot.NPC.Install-Citizens", ""));
messageManager.registerMessage("MENU_PERMISSION", new Message("Menu.Permission", ""));
messageManager.registerMessage("MENU_BUTTONS_BACK_ITEM_NAME", new Message("Menu.Buttons.Back.Item.Name", ""));
messageManager.registerMessage("MENU_BUTTONS_BACK_ITEM_LORE", new Message("Menu.Buttons.Back.Item.Lore", ""));
messageManager.registerMessage("MENU_LOCATION", new Message("Menu.Location", ""));
messageManager.registerMessage("MENU_OPTION_INVENTORY", new Message("Menu.Option.Inventory", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_PARTICLE_INVENTORY",
new Message("Menu.Option.Content.Particle.Inventory", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_PARTICLE_ITEM_NAME",
new Message("Menu.Option.Content.Particle.Item.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_PARTICLE_ITEM_LORE",
new Message("Menu.Option.Content.Particle.Item.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_PARTICLE_ITEM_REMOVE_NAME",
new Message("Menu.Option.Content.Particle.Item.Remove.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_PARTICLE_ITEM_REMOVE_LORE",
new Message("Menu.Option.Content.Particle.Item.Remove.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_PARTICLE_ADDED",
new Message("Menu.Option.Content.Particle.Added", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_PARTICLE_REMOVED",
new Message("Menu.Option.Content.Particle.Removed", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_HEADS_INVENTORY",
new Message("Menu.Option.Content.Heads.Inventory", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_HEADS_ITEM_NAME",
new Message("Menu.Option.Content.Heads.Item.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_HEADS_ITEM_LORE",
new Message("Menu.Option.Content.Heads.Item.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_HEADS_DATABASE_LORE",
new Message("Menu.Option.Content.Heads.Database.Lore", "Get Head %value%"));
messageManager.registerMessage("MENU_OPTION_CONTENT_FLOOR_ITEM_NAME",
new Message("Menu.Option.Content.Floor.Item.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_FLOOR_ITEM_LORE",
new Message("Menu.Option.Content.Floor.Item.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_FLOOR_CHANGED",
new Message("Menu.Option.Content.Floor.Changed", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_INVENTORY",
new Message("Menu.Option.Content.Time.Inventory", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_ITEM_NAME",
new Message("Menu.Option.Content.Time.Item.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_ITEM_LORE",
new Message("Menu.Option.Content.Time.Item.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_TYPE_WORLD",
new Message("Menu.Option.Content.Time.Type.World", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_TYPE_DAY",
new Message("Menu.Option.Content.Time.Type.Day", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_TYPE_NOON",
new Message("Menu.Option.Content.Time.Type.Noon", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_TYPE_SUNSET",
new Message("Menu.Option.Content.Time.Type.Sunset", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_TYPE_NIGHT",
new Message("Menu.Option.Content.Time.Type.Night", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_TYPE_MIDNIGHT",
new Message("Menu.Option.Content.Time.Type.MidNight", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_TYPE_SUNRISE",
new Message("Menu.Option.Content.Time.Type.Sunrise", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_TIME_CHANGED",
new Message("Menu.Option.Content.Time.Changed", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BIOME_INVENTORY",
new Message("Menu.Option.Content.Biome.Inventory", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BIOME_ITEM_NAME",
new Message("Menu.Option.Content.Biome.Item.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BIOME_ITEM_LORE",
new Message("Menu.Option.Content.Biome.Item.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BIOME_CHANGED",
new Message("Menu.Option.Content.Biome.Changed", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_WEATHER_INVENTORY",
new Message("Menu.Option.Content.Weather.Inventory", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_WEATHER_ITEM_NAME",
new Message("Menu.Option.Content.Weather.Item.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_WEATHER_ITEM_LORE",
new Message("Menu.Option.Content.Weather.Item.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_WEATHER_TYPE_DOWNFALL",
new Message("Menu.Option.Content.Weather.Type.Downfall", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_WEATHER_TYPE_CLEAR",
new Message("Menu.Option.Content.Weather.Type.Clear", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_WEATHER_CHANGED",
new Message("Menu.Option.Content.Weather.Changed", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BANNER_INVENTORY_COLOR",
new Message("Menu.Option.Content.Banner.Inventory.Color", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BANNER_INVENTORY_LAYER",
new Message("Menu.Option.Content.Banner.Inventory.Layer", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BANNER_INVENTORY_LAYER_COLOR",
new Message("Menu.Option.Content.Banner.Inventory.Layer-Color", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BANNER_ITEM_NAME",
new Message("Menu.Option.Content.Banner.Item.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BANNER_ITEM_LORE",
new Message("Menu.Option.Content.Banner.Item.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BANNER_ITEM_CREATE_NAME",
new Message("Menu.Option.Content.Banner.Item.Create.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BANNER_ITEM_CREATE_LORE",
new Message("Menu.Option.Content.Banner.Item.Create.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_BANNER_CHANGED",
new Message("Menu.Option.Content.Banner.Changed", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_RESET_ITEM_NAME",
new Message("Menu.Option.Content.Reset.Item.Name", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_RESET_ITEM_LORE",
new Message("Menu.Option.Content.Reset.Item.Lore", ""));
messageManager.registerMessage("MENU_OPTION_CONTENT_RESET_CHAT",
new Message("Menu.Option.Content.Reset.Chat", ""));
messageManager.registerMessage("MENU_THEME_INVENTORY", new Message("Menu.Theme.Inventory", ""));
messageManager.registerMessage("MENU_THEME_ITEM_NAME", new Message("Menu.Theme.Item.Name", ""));
messageManager.registerMessage("MENU_THEME_ITEM_LORE", new Message("Menu.Theme.Item.Lore", ""));
messageManager.registerMessage("MENU_THEME_VOTE_SUCCESS", new Message("Menu.Theme.Vote.Success", ""));
messageManager.registerMessage("MENU_THEME_VOTE_ALREADY", new Message("Menu.Theme.Vote.Already", ""));
messageManager.registerMessage("MENU_THEME_VOTE_SUPER_ITEM_NAME",
new Message("Menu.Theme.Vote.Super.Item.Name", ""));
messageManager.registerMessage("MENU_THEME_VOTE_SUPER_ITEM_LORE",
new Message("Menu.Theme.Vote.Super.Item.Lore", ""));
messageManager.registerMessage("MENU_THEME_VOTE_SUPER_USED", new Message("Menu.Theme.Vote.Super.Used", ""));
messageManager.registerMessage("MENU_THEME_GTB_INVENTORY",
new Message("Menu.Theme.Guess-The-Build.Inventory", ""));
messageManager.registerMessage("MENU_THEME_GTB_ITEM_NAME",
new Message("Menu.Theme.Guess-The-Build.Item.Name", ""));
messageManager.registerMessage("MENU_THEME_GTB_ITEM_LORE",
new Message("Menu.Theme.Guess-The-Build.Item.Lore", ""));
messageManager.registerMessage("MENU_THEME_GTB_DIFFICULTIES_EASY",
new Message("Menu.Theme.Guess-The-Build.Difficulties.Easy", ""));
messageManager.registerMessage("MENU_THEME_GTB_DIFFICULTIES_MEDIUM",
new Message("Menu.Theme.Guess-The-Build.Difficulties.Medium", ""));
messageManager.registerMessage("MENU_THEME_GTB_DIFFICULTIES_HARD",
new Message("Menu.Theme.Guess-The-Build.Difficulties.Hard", ""));
messageManager.registerMessage("LEADERBOARD_STATISTICS_POINTS_HIGHEST_WIN",
new Message("Leaderboard.Statistics.Highest-Win", ""));
messageManager.registerMessage("LEADERBOARD_STATISTICS_POINTS_HIGHEST",
new Message("Leaderboard.Statistics.Highest-Points", ""));
messageManager.registerMessage("LEADERBOARD_STATISTICS_POINTS_TOTAL",
new Message("Leaderboard.Statistics.Total-Points-Earned", ""));
messageManager.registerMessage("LEADERBOARD_STATISTICS_BLOCKS_PLACED",
new Message("Leaderboard.Statistics.Blocks-Placed", ""));
messageManager.registerMessage("LEADERBOARD_STATISTICS_BLOCKS_BROKEN",
new Message("Leaderboard.Statistics.Blocks-Broken", ""));
messageManager.registerMessage("LEADERBOARD_STATISTICS_PARTICLES_USED",
new Message("Leaderboard.Statistics.Particles-Placed", ""));
messageManager.registerMessage("LEADERBOARD_STATISTICS_SUPER_VOTES",
new Message("Leaderboard.Statistics.Super-Votes", ""));
}
}
@@ -0,0 +1,872 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.boot;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.arena.GuessArena;
import plugily.projects.buildbattle.arena.managers.plots.Plot;
import plugily.projects.buildbattle.handlers.themes.GuessTheme;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.placeholder.Placeholder;
import plugily.projects.minigamesbox.classic.handlers.placeholder.PlaceholderManager;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Tigerpanzer_02
* <p>
* Created at 15.10.2022
*/
public class PlaceholderInitializer {
private final Main plugin;
public PlaceholderInitializer(Main plugin) {
this.plugin = plugin;
registerPlaceholders();
}
private void registerPlaceholders() {
PlaceholderManager placeholderManager = plugin.getPlaceholderManager();
ArenaRegistry arenaRegistry = plugin.getArenaRegistry();
placeholderManager.registerPlaceholder(
new Placeholder("theme", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getTheme(player, arena);
}
@Override
public String getValue(IPluginArena arena) {
return getTheme(arena);
}
@Nullable
private String getTheme(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
String theme = pluginArena.getTheme();
if (theme == null) {
theme = new MessageBuilder("SCOREBOARD_THEME_UNKNOWN").asKey().build();
}
return theme;
}
@Nullable
private String getTheme(Player player, IPluginArena arena) {
String theme = getTheme(arena);
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
if (!(pluginArena instanceof GuessArena)) {
return theme;
}
if (theme.equalsIgnoreCase(new MessageBuilder("SCOREBOARD_THEME_UNKNOWN").asKey().build())) {
if (((GuessArena) pluginArena).getCurrentBuilders().contains(player)
|| ((GuessArena) pluginArena).getWhoGuessed().contains(player))
{
GuessTheme guessTheme = ((GuessArena) pluginArena).getCurrentBBTheme();
theme = guessTheme == null
? new MessageBuilder("SCOREBOARD_THEME_UNKNOWN").asKey().build()
: guessTheme.getDefaultTheme();
}
}
return theme;
}
});
placeholderManager.registerPlaceholder(
new Placeholder("difficulty", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getTheme(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getTheme(arena);
}
@Nullable
private String getTheme(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena instanceof GuessArena) {
GuessTheme theme = ((GuessArena) pluginArena).getCurrentBBTheme();
if (theme == null) {
return null;
}
return theme.getDifficulty().name();
}
return null;
}
});
placeholderManager.registerPlaceholder(new Placeholder("difficulty_points_reward",
Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getTheme(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getTheme(arena);
}
@Nullable
private String getTheme(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena instanceof GuessArena) {
GuessTheme theme = ((GuessArena) pluginArena).getCurrentBBTheme();
if (theme == null) {
return "0";
}
return Integer.toString(theme.getDifficulty().getPointsReward());
}
return null;
}
});
placeholderManager.registerPlaceholder(
new Placeholder("builder", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getBuilder(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getBuilder(arena);
}
@Nullable
private String getBuilder(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (!(pluginArena instanceof GuessArena)) {
return null;
}
if (((GuessArena) pluginArena).getBuildPlot() == null
|| ((GuessArena) pluginArena).getBuildPlot().getMembers().isEmpty())
{
return "???";
}
return ((GuessArena) pluginArena).getBuildPlot().getFormattedMembers();
}
});
placeholderManager.registerPlaceholder(
new Placeholder("type", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getType(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getType(arena);
}
@Nullable
private String getType(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
return pluginArena.getArenaType().toString();
}
});
placeholderManager.registerPlaceholder(
new Placeholder("type_pretty", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getType(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getType(arena);
}
@Nullable
private String getType(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
return pluginArena.getArenaType().getPrefix();
}
});
for (int i = 1; i <= 32; i++) {
final int number = i;
placeholderManager.registerPlaceholder(new Placeholder("place_member_" + number,
Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getPlace(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getPlace(arena);
}
@Nullable
private String getPlace(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
if (pluginArena.getArenaInGameState() != BaseArena.ArenaInGameState.PLOT_VOTING
&& pluginArena.getArenaState() != IArenaState.ENDING)
{
return "???";
}
List<Plot> plotRanking = pluginArena.getPlotManager().getTopPlotsOrder();
if (plotRanking.size() < number) {
return "???";
}
StringBuilder members = new StringBuilder();
plotRanking.get(number - 1).getMembers()
.forEach(player -> members.append(player.getName()).append(" & "));
members.delete(members.length() - 3, members.length());
return new MessageBuilder(members.toString()).build();
}
});
placeholderManager.registerPlaceholder(new Placeholder("place_points_" + number,
Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getPlace(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getPlace(arena);
}
@Nullable
private String getPlace(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
if (pluginArena.getArenaInGameState() != BaseArena.ArenaInGameState.PLOT_VOTING
&& pluginArena.getArenaState() != IArenaState.ENDING)
{
return "???";
}
List<Plot> plotRanking = pluginArena.getPlotManager().getTopPlotsOrder();
if (plotRanking.size() < number) {
return "???";
}
return String.valueOf(plotRanking.get(number - 1).getPoints());
}
});
}
placeholderManager.registerPlaceholder(
new Placeholder("ingame_state", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getState(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getState(arena);
}
@Nullable
private String getState(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
if (pluginArena.getArenaInGameState() == null) {
return null;
}
return pluginArena.getArenaInGameState().toString();
}
});
placeholderManager.registerPlaceholder(new Placeholder("ingame_state_pretty", Placeholder.PlaceholderType.ARENA,
Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getState(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getState(arena);
}
@Nullable
private String getState(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
if (pluginArena.getArenaInGameState() == null) {
return null;
}
return pluginArena.getArenaInGameState().getPrefix();
}
});
placeholderManager.registerPlaceholder(
new Placeholder("teammates", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getMembers(player, arena);
}
@Nullable
private String getMembers(Player player, IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
if (!(pluginArena instanceof BuildArena)) {
return new MessageBuilder("IN_GAME_MESSAGES_PLOT_NOBODY").asKey().build();
}
Plot plot = pluginArena.getPlotManager().getPlot(player);
if (plot != null) {
if (plot.getMembers().size() > 1) {
StringBuilder members = new StringBuilder();
plot.getMembers().forEach(p -> members.append(p.getName()).append(" & "));
members.delete(members.length() - 3, members.length());
return new MessageBuilder(members.toString()).build();
}
}
return new MessageBuilder("IN_GAME_MESSAGES_PLOT_NOBODY").asKey().build();
}
});
placeholderManager.registerPlaceholder(new Placeholder("summary_player", Placeholder.PlaceholderType.ARENA,
Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getSummary(arena, player);
}
@Nullable
private String getSummary(IPluginArena arena, Player player) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
Plot plot = pluginArena.getWinnerPlot();
if (plot != null && !plot.getMembers().isEmpty() && plot.getMembers().contains(player)) {
return new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_WIN").asKey().arena(pluginArena)
.build();
}
return new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_LOSE").asKey().arena(pluginArena)
.build();
}
});
placeholderManager.registerPlaceholder(new Placeholder("summary_place_own", Placeholder.PlaceholderType.ARENA,
Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getSummary(arena, player);
}
@Nullable
private String getSummary(IPluginArena arena, Player player) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
if (pluginArena.getArenaInGameState() != BaseArena.ArenaInGameState.PLOT_VOTING
&& pluginArena.getArenaState() != IArenaState.ENDING)
{
return null;
}
List<Plot> plotRanking = pluginArena.getPlotManager().getTopPlotsOrder();
List<Plot> potentialPlot = plotRanking.stream().filter(plot -> plot.getMembers().contains(player))
.collect(Collectors.toList());
if (potentialPlot.isEmpty()) {
return new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_OWN").asKey().integer(0)
.arena(pluginArena).build();
}
int plotIndex = plotRanking.indexOf(potentialPlot.get(0));
if (plotIndex == -1) {
return new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_OWN").asKey().integer(0)
.arena(pluginArena).build();
}
return new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_OWN").asKey().integer(plotIndex + 1)
.arena(pluginArena).build();
}
});
placeholderManager.registerPlaceholder(
new Placeholder("summary", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getSummary(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getSummary(arena);
}
@Nullable
private String getSummary(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
Plot plot = pluginArena.getWinnerPlot();
if (plot != null && !plot.getMembers().isEmpty()) {
return new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_WINNER").asKey()
.arena(pluginArena).build();
}
return null;
}
});
placeholderManager.registerPlaceholder(new Placeholder("summary_place_list", Placeholder.PlaceholderType.ARENA,
Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getSummary(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getSummary(arena);
}
@Nullable
private String getSummary(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
if (pluginArena.getArenaInGameState() != BaseArena.ArenaInGameState.PLOT_VOTING
&& pluginArena.getArenaState() != IArenaState.ENDING)
{
return null;
}
int places = pluginArena.getPlotManager().getTopPlotsOrder().size();
if (places > 20) {
places = 20;
}
StringBuilder placeSummary = new StringBuilder();
for (int i = 1; i <= places; i++) {
// number = place, value = members + points
placeSummary.append("\n")
.append(new MessageBuilder("IN_GAME_MESSAGES_GAME_END_PLACEHOLDERS_PLACE").asKey()
.integer(i).value("%arena_place_member_" + i + "% (%arena_place_points_" + i + "%)")
.arena(pluginArena).build());
}
return placeSummary.toString();
}
});
placeholderManager.registerPlaceholder(
new Placeholder("gtb_rounds", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getSummary(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getSummary(arena);
}
@Nullable
private String getSummary(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena == null) {
return null;
}
return String.valueOf(
pluginArena.getPlotList().size() * pluginArena.getArenaOption("GTB_ROUNDS_PER_PLOT"));
}
});
placeholderManager.registerPlaceholder(
new Placeholder("round", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getRound(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getRound(arena);
}
// The running round of either mode.
@Nullable
private String getRound(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena instanceof GuessArena) {
return String.valueOf(((GuessArena) pluginArena).getRound());
}
if (pluginArena instanceof BuildArena) {
return String.valueOf(((BuildArena) pluginArena).getRound());
}
return null;
}
});
placeholderManager.registerPlaceholder(
new Placeholder("rounds", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL)
{
@Override
public String getValue(Player player, IPluginArena arena) {
return getRounds(arena);
}
@Override
public String getValue(IPluginArena arena) {
return getRounds(arena);
}
// Classic and Teams rounds; plots x rounds per plot in GTB.
@Nullable
private String getRounds(IPluginArena arena) {
BaseArena pluginArena = arenaRegistry.getArena(arena.getId());
if (pluginArena instanceof GuessArena) {
return String.valueOf(pluginArena.getPlotList().size()
* pluginArena.getArenaOption("GTB_ROUNDS_PER_PLOT"));
}
if (pluginArena instanceof BuildArena) {
return String.valueOf(((BuildArena) pluginArena).getRounds());
}
return null;
}
});
}
}
@@ -0,0 +1,40 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.boot;
import org.bukkit.entity.Player;
import net.trueog.utilitiesog.UtilitiesOG;
import plugily.projects.buildbattle.handlers.stats.BuildBattleScores;
// Registers the bb_score and bb_rank MiniPlaceholders through Utilities-OG.
// Only constructed when Utilities-OG is installed, so its classes stay unloaded otherwise.
public class TrueOGPlaceholderInitializer {
public TrueOGPlaceholderInitializer(BuildBattleScores scores) {
UtilitiesOG.registerAudiencePlaceholder("bb_score",
(Player player) -> String.valueOf(scores.getPoints(player.getUniqueId())));
UtilitiesOG.registerAudiencePlaceholder("bb_rank",
(Player player) -> scores.getRank(player.getUniqueId()).getDisplay());
}
}
@@ -0,0 +1,134 @@
package plugily.projects.buildbattle.chat;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.trueog.utilitiesog.UtilitiesOG;
import nl.skbotnl.chatog.api.WorldChatFormatter;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.minigamesbox.api.arena.IArenaState;
// Renders BuildBattle chat now that Chat-OG owns delivery and the Discord relay.
//
// The arena is resolved from the sender rather than the lobby id Chat-OG passes, so a spectator or
// a staff member standing in an arena world without having joined still falls through to Chat-OG's
// default format instead of being labelled as a competitor.
//
// The theme is never rendered for Guess the Build: it is the answer, and Discord relays this line.
//
// The name segment mirrors TheHerobrine-OG's formatter: the standard TrueOG
// union bracket tag, display name, and LuckPerms suffix, expanded through
// MiniPlaceholders with the sender as the audience so the same content reaches
// the in-game view and the Discord relay.
public class BuildBattleChatFormatter implements WorldChatFormatter {
private static final String NAME_SEGMENT = "<simpleclans_union_bracket_tag><player_display_name><luckperms_suffix> ";
private final Main plugin;
public BuildBattleChatFormatter(Main plugin) {
this.plugin = plugin;
}
@Override
public Component format(Player sender, Component message, String worldName, String lobbyId) {
BaseArena arena = plugin.getArenaRegistry().getArena(sender);
if (arena == null) {
return null;
}
final Component prefix = UtilitiesOG.trueogExpand(buildPrefix(sender, arena), sender);
// The caret never inherits bold or colors from the prefix.
final Component caret = UtilitiesOG.trueogExpand(getCaretColor(sender) + "> &r", sender)
.decoration(TextDecoration.BOLD, false);
// The message is already sanitised by Chat-OG, so it is composed with rather
// than re-parsed.
return Component.join(JoinConfiguration.noSeparators(), prefix, caret, message);
}
private String buildPrefix(Player player, BaseArena arena) {
if (arena.getSpectators().contains(player)) {
return "&4SPEC &8▏ " + NAME_SEGMENT;
}
IArenaState state = arena.getArenaState();
if (state == IArenaState.WAITING_FOR_PLAYERS || state == IArenaState.STARTING
|| state == IArenaState.FULL_GAME)
{
return "&e" + arena.getPlayers().size() + "&7/&e" + arena.getMaximumPlayers() + "&8 ▏ " + NAME_SEGMENT;
}
if (state != IArenaState.IN_GAME) {
return NAME_SEGMENT;
}
switch (arena.getArenaInGameState()) {
case THEME_VOTING:
return "&6VOTE &8▏ " + NAME_SEGMENT;
case PLOT_VOTING:
return "&6JUDGING &8▏ " + NAME_SEGMENT;
case BUILD_TIME:
// Only a classic/team arena has a theme worth showing; leaking a Guess the
// Build theme here would hand the answer to the world and to Discord.
String theme = arena instanceof BuildArena ? arena.getTheme() : null;
return theme == null || theme.isEmpty() ? NAME_SEGMENT : "&a" + theme + " &8▏ " + NAME_SEGMENT;
default:
return NAME_SEGMENT;
}
}
// TODO: Expose PlayerUtils.getMessageColor in Chat-OG as a supported API.
private String getCaretColor(Player player) {
try {
final net.kyori.adventure.text.format.TextColor color = nl.skbotnl.chatog.util.PlayerUtils.INSTANCE
.getMessageColor(player.getUniqueId());
if (color != null) {
if (color.equals(NamedTextColor.WHITE)) {
return "&f";
} else if (color.equals(NamedTextColor.GRAY)) {
return "&7";
}
}
} catch (Throwable ignored) {
// Chat-OG internals moved or are absent -- fall back to dark gray.
}
return "&8";
}
}
@@ -0,0 +1,62 @@
package plugily.projects.buildbattle.commands;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import plugily.projects.buildbattle.Main;
import plugily.projects.minigamesbox.classic.arena.PluginArenaUtils;
// Starts the arena the sender is in even when the minimum player count is unmet.
// PluginArenaUtils.arenaForceStart owns the permission, state, and timer checks.
public class ForceStartCommand implements CommandExecutor {
private final Main plugin;
private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacyAmpersand();
public ForceStartCommand(Main plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage("Only players can use this command.");
return true;
}
int startTime = 0;
if (args.length > 0) {
try {
startTime = Integer.parseInt(args[0]);
} catch (NumberFormatException error) {
send(player, "&cCorrect Usage: /bbforcestart [time]");
return true;
}
}
PluginArenaUtils.arenaForceStart(player, Math.max(0, startTime));
return true;
}
private void send(Player player, String message) {
player.sendMessage(LEGACY_SERIALIZER.deserialize(plugin.getPluginMessagePrefix() + message));
}
}
@@ -0,0 +1,107 @@
package plugily.projects.buildbattle.commands;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.minigamesbox.classic.utils.serialization.InventorySerializer;
// /hub and /lobby. Leaves the arena the player is in and sends them back where
// they came from, or to main spawn. HubCommandListener routes /hub, /lobby and
// /spawn here for anyone inside BuildBattle territory, whichever plugin owns
// the bare label.
public class HubCommand implements CommandExecutor {
private final Main plugin;
private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacyAmpersand();
public HubCommand(Main plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage("Only players can use this command.");
return true;
}
handle(player);
return true;
}
public void handle(Player player) {
BaseArena arena = plugin.getArenaRegistry().getArena(player);
if (arena != null) {
plugin.getArenaManager().hubLeaveAttempt(player, arena);
// The MiniGamesBox snapshot belongs to the arena world's MyWorlds inventory,
// so it goes back before the teleport home, not over the survival one.
InventorySerializer.loadInventory(plugin, player);
}
Location savedLoc = plugin.getAndRemovePreJoinLocation(player.getUniqueId());
if (savedLoc != null && savedLoc.getWorld() != null) {
if (!player.teleport(savedLoc)) {
send(player, "&cUnable to return you to your previous location.");
return;
}
plugin.getBuilderCreativeManager().revoke(player);
send(player, "&aReturned to your previous location.");
return;
}
// MyWorlds' main world spawn is what Spawn-OG's /setspawn writes, so this
// lands on the server spawn.
World mainWorld = findMainWorld();
if (mainWorld == null) {
send(player, "&cNo main world is available.");
return;
}
Location destination = mainWorld.getSpawnLocation();
if (!player.teleport(destination)) {
send(player, "&cUnable to return you to the hub.");
return;
}
plugin.getBuilderCreativeManager().revoke(player);
send(player, "&aReturned to the hub.");
}
private World findMainWorld() {
return plugin.getMyWorldsManager().getMainWorld();
}
private void send(Player player, String message) {
player.sendMessage(LEGACY_SERIALIZER.deserialize(plugin.getPluginMessagePrefix() + message));
}
}
@@ -0,0 +1,85 @@
package plugily.projects.buildbattle.commands;
import java.util.Locale;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import plugily.projects.buildbattle.Main;
// Claims /hub, /lobby and /spawn for arena members and anyone standing in a
// configured BuildBattle world. BuildBattle-OG, Splegg-OG and TheHerobrine-OG
// all declare /hub, and Bukkit hands the bare label to whichever registered
// first, so without this a BuildBattle player's /hub could run another
// minigame's command and teleport them out while the arena still counted them;
// /spawn from Spawn-OG did the same. Everywhere else the event is left alone.
public class HubCommandListener implements Listener {
private final Main plugin;
private final HubCommand hubCommand;
public HubCommandListener(Main plugin, HubCommand hubCommand) {
this.plugin = plugin;
this.hubCommand = hubCommand;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onCommandPreprocess(PlayerCommandPreprocessEvent event) {
final String label = commandLabel(event.getMessage());
if (!label.equals("hub") && !label.equals("lobby") && !label.equals("spawn")) {
return;
}
final Player player = event.getPlayer();
if (plugin.getArenaRegistry().getArena(player) == null
&& !plugin.getMyWorldsManager().isConfiguredArenaWorld(player.getWorld().getName()))
{
return;
}
event.setCancelled(true);
hubCommand.handle(player);
}
// The bare command name in lower case, without the leading slash or a
// plugin namespace such as buildbattle-og:hub.
static String commandLabel(String message) {
if (message == null || message.length() < 2 || message.charAt(0) != '/') {
return "";
}
final String[] parts = message.substring(1).trim().split("\\s+");
if (parts.length == 0) {
return "";
}
String label = parts[0].toLowerCase(Locale.ROOT);
final int colon = label.indexOf(':');
if (colon >= 0) {
label = label.substring(colon + 1);
}
return label;
}
}
@@ -0,0 +1,91 @@
package plugily.projects.buildbattle.commands;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.BaseArena;
// Joins a BuildBattle lobby by its id (BB1 or 1); with no id the lobby list is
// shown. Maps and themes are not accepted.
public class JoinLobbyCommand implements CommandExecutor, TabCompleter {
private final Main plugin;
private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacyAmpersand();
public JoinLobbyCommand(Main plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage("Only players can use this command.");
return true;
}
if (args.length == 0) {
LobbyList.send(plugin, player);
return true;
}
final BaseArena arena = LobbyResolver.resolve(plugin, args[0]);
if (arena == null) {
send(player, "&cLobby &e" + args[0] + " &cdoes not exist.");
LobbyList.send(plugin, player);
return true;
}
plugin.getArenaManager().joinAttempt(player, arena);
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length != 1) {
return null;
}
final String prefix = LobbyResolver.normalize(args[0]);
final List<String> completions = new ArrayList<>();
for (String id : LobbyResolver.lobbyIds(plugin)) {
if (LobbyResolver.normalize(id).startsWith(prefix)) {
completions.add(id);
}
}
return completions;
}
private void send(Player player, String message) {
player.sendMessage(LEGACY_SERIALIZER.deserialize(plugin.getPluginMessagePrefix() + message));
}
}
@@ -0,0 +1,106 @@
package plugily.projects.buildbattle.commands;
import java.util.List;
import org.bukkit.entity.Player;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import plugily.projects.buildbattle.Main;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
// The lobby list players see from /bb join and /bbjoin with no lobby named,
// TheHerobrine-OG style: one clickable line per arena with its state and fill.
public final class LobbyList {
private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacyAmpersand();
private LobbyList() {
}
public static void send(Main plugin, Player player) {
final List<IPluginArena> arenas = plugin.getArenaRegistry().getArenas();
if (arenas.isEmpty()) {
send(player, plugin, "&cThere are no BuildBattle lobbies. Create one with /bba setup create <BB1>.");
return;
}
send(player, plugin, "&6Join a lobby with /bb join <id>.");
send(player, plugin, "&6Lobbies available to join:");
final boolean overfill = player.hasPermission("buildbattle.fullgames");
for (IPluginArena arena : arenas) {
final String id = arena.getId();
final int fill = arena.getPlayers().size();
final int max = arena.getMaximumPlayers();
final String line;
final String hover;
switch (arena.getArenaState()) {
case WAITING_FOR_PLAYERS, STARTING, FULL_GAME -> {
final boolean room = fill < max;
final String state = arena.getArenaState() == IArenaState.WAITING_FOR_PLAYERS ? "&e&lWAITING "
: "&d&lSTARTING ";
line = "&b" + id + ": &e" + fill + "/" + max + "&7 - &r"
+ (room ? state + "&r&a(JOIN)" : "&c&lFULL &r" + (overfill ? "&a(JOIN)" : ""));
hover = room || overfill ? "&6Click here to join &b" + id : null;
}
case IN_GAME -> {
line = "&b" + id + ": &e" + fill + " playing&8 - &b&lLIVE &2(SPECTATE)";
hover = "&6Click here to spectate &b" + id;
}
case ENDING -> {
line = "&b" + id + ": &8&lENDING";
hover = null;
}
default -> {
line = "&b" + id + ": &8&lRESTARTING";
hover = null;
}
}
TextComponent component = LEGACY_SERIALIZER.deserialize(plugin.getPluginMessagePrefix() + line);
if (hover != null) {
component = component
.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
LEGACY_SERIALIZER.deserialize(hover)))
.clickEvent(ClickEvent.runCommand("/bb join " + id));
} else {
component = component.hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT,
LEGACY_SERIALIZER.deserialize("&cThis lobby cannot be joined right now.")));
}
player.sendMessage(component);
}
}
private static void send(Player player, Main plugin, String message) {
player.sendMessage(LEGACY_SERIALIZER.deserialize(plugin.getPluginMessagePrefix() + message));
}
}
@@ -0,0 +1,146 @@
package plugily.projects.buildbattle.commands;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
// Resolves the lobby id a player typed (BB1) to an arena. Bare numbers are
// accepted so /bbjoin 1 matches BB1, and matching is case-insensitive.
// Map names and themes are never resolvable -- only lobby ids.
public final class LobbyResolver {
private LobbyResolver() {
}
public static BaseArena resolve(Main plugin, String input) {
if (input == null) {
return null;
}
final String query = input.trim();
if (query.isEmpty()) {
return null;
}
for (IPluginArena arena : plugin.getArenaRegistry().getArenas()) {
if (arena.getId().equalsIgnoreCase(query)) {
return plugin.getArenaRegistry().getArena(arena.getId());
}
}
if (!isNumber(query)) {
return null;
}
// Bare number: match the trailing digits of a lobby id so "1" finds BB1
// whatever prefix the server configured. Ambiguity is a miss, not a guess.
final int wanted = Integer.parseInt(query);
BaseArena match = null;
for (IPluginArena arena : plugin.getArenaRegistry().getArenas()) {
if (trailingNumber(arena.getId()) != wanted) {
continue;
}
if (match != null) {
return null;
}
match = plugin.getArenaRegistry().getArena(arena.getId());
}
return match;
}
public static List<String> lobbyIds(Main plugin) {
final List<String> ids = new ArrayList<>();
for (IPluginArena arena : plugin.getArenaRegistry().getArenas()) {
ids.add(arena.getId());
}
return ids;
}
// Returns the number a lobby id ends with, or -1 when it ends in a letter.
private static int trailingNumber(String id) {
int index = id.length();
while (index > 0 && Character.isDigit(id.charAt(index - 1))) {
index--;
}
if (index == id.length()) {
return -1;
}
try {
return Integer.parseInt(id.substring(index));
} catch (NumberFormatException error) {
return -1;
}
}
private static boolean isNumber(String value) {
if (value.length() > 9) {
return false;
}
for (int i = 0; i < value.length(); i++) {
if (!Character.isDigit(value.charAt(i))) {
return false;
}
}
return true;
}
public static String normalize(String value) {
return value == null ? "" : value.toLowerCase(Locale.ROOT);
}
}
@@ -1,101 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.commands;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Plajer
* <p>
* Created at 27.05.2018
*/
public class TabCompletion implements TabCompleter {
private final ArgumentsRegistry registry;
public TabCompletion(ArgumentsRegistry registry) {
this.registry = registry;
}
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, Command cmd, @NotNull String label, String[] args) {
List<String> cmds = new ArrayList<>();
if(cmd.getName().equalsIgnoreCase("buildbattleadmin")) {
if(args.length == 1) {
cmds.addAll(registry.getMappedArguments().get("buildbattleadmin").stream().map(CommandArgument::getArgumentName)
.collect(Collectors.toList()));
} else if(args.length == 2) {
if(args[0].equalsIgnoreCase("delete") || args[0].equalsIgnoreCase("removeplot")
|| args[0].equalsIgnoreCase("addnpc") || args[0].equalsIgnoreCase("addplot")) {
cmds.addAll(ArenaRegistry.getArenas().stream().map(BaseArena::getID).collect(Collectors.toList()));
} else if(args[0].equalsIgnoreCase("settheme")) {
for(List<String> l : registry.getPlugin().getConfigPreferences().getGameThemes().values()) {
cmds.addAll(l);
}
} else if(args[0].equalsIgnoreCase("votes")) {
cmds.addAll(Arrays.asList("add", "set"));
}
} else if(args.length == 3 && args[0].equalsIgnoreCase("removeplot")) {
BaseArena arena = ArenaRegistry.getArena(args[1]);
if (arena != null) {
FileConfiguration config = ConfigUtils.getConfig(registry.getPlugin(), "arenas");
org.bukkit.configuration.ConfigurationSection section =
config.getConfigurationSection("instances." + arena.getID() + ".plots");
if (section != null) {
cmds.addAll(section.getKeys(false));
}
}
}
return cmds.isEmpty() ? null : cmds; // Completes the player names
}
if(cmd.getName().equalsIgnoreCase("buildbattle")) {
if(args.length == 2 && (args[0].equalsIgnoreCase("join") || args[0].equalsIgnoreCase("randomjoin"))) {
if(args[0].equalsIgnoreCase("randomjoin")) {
cmds.addAll(Arrays.asList("solo", "team", "gtb", "guess_the_build"));
} else {
cmds.addAll(ArenaRegistry.getArenas().stream().map(BaseArena::getID).collect(Collectors.toList()));
}
} else if(args.length == 1) {
cmds.addAll(registry.getMappedArguments().get("buildbattle").stream().map(CommandArgument::getArgumentName)
.collect(Collectors.toList()));
}
}
return cmds.isEmpty() ? null : cmds; // Completes the player names
}
}
@@ -0,0 +1,210 @@
package plugily.projects.buildbattle.commands;
import java.util.List;
import java.util.Locale;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.handlers.themes.vote.VotePoll;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
// Routes /v and /vote to the arena's existing theme poll inside BuildBattle
// worlds only. BuildBattle has no map pool, so this drives the poll the vote
// menu already owns -- it exists so VotingPlugin cannot own /vote in a lobby.
public class VoteCommandListener implements Listener {
private final Main plugin;
private static final LegacyComponentSerializer LEGACY_SERIALIZER = LegacyComponentSerializer.legacyAmpersand();
public VoteCommandListener(Main plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onCommandPreprocess(PlayerCommandPreprocessEvent event) {
final String message = event.getMessage();
if (message == null || message.length() < 2 || message.charAt(0) != '/') {
return;
}
final String[] parts = message.substring(1).trim().split("\\s+");
if (parts.length == 0 || parts[0].isEmpty()) {
return;
}
// Drop any namespace prefix (e.g. votingplugin:v) before matching.
String label = parts[0].toLowerCase(Locale.ROOT);
final int colon = label.indexOf(':');
if (colon >= 0) {
label = label.substring(colon + 1);
}
if (!label.equals("v") && !label.equals("vote")) {
return;
}
final Player player = event.getPlayer();
final BaseArena arena = resolveArena(player);
if (arena == null) {
return;
}
event.setCancelled(true);
handleVote(player, arena, parts.length > 1 ? parts[1] : null);
}
// Claims the command for an arena member, or for anyone standing in a
// configured BuildBattle world. Defers everywhere else.
private BaseArena resolveArena(Player player) {
final BaseArena arena = plugin.getArenaRegistry().getArena(player);
if (arena != null) {
return arena;
}
return plugin.getMyWorldsManager().isConfiguredArenaWorld(player.getWorld().getName()) ? findWorldArena(player)
: null;
}
private BaseArena findWorldArena(Player player) {
final String worldName = player.getWorld().getName();
for (String id : LobbyResolver.lobbyIds(plugin)) {
final BaseArena candidate = plugin.getArenaRegistry().getArena(id);
if (candidate == null) {
continue;
}
if (matchesWorld(candidate.getLobbyLocation(), worldName)
|| matchesWorld(candidate.getStartLocation(), worldName))
{
return candidate;
}
}
return null;
}
private boolean matchesWorld(org.bukkit.Location location, String worldName) {
return location != null && location.getWorld() != null && location.getWorld().getName().equals(worldName);
}
private void handleVote(Player player, BaseArena arena, String argument) {
if (!(arena instanceof BuildArena buildArena)) {
send(player, "&cThere is nothing to vote for in this game mode.");
return;
}
if (arena.getArenaState() != IArenaState.IN_GAME
|| arena.getArenaInGameState() != BaseArena.ArenaInGameState.THEME_VOTING)
{
send(player, "&cYou cannot run this command right now.");
return;
}
final VotePoll votePoll = buildArena.getVotePoll();
final List<String> themes = buildArena.getVoteMenu().getThemeSelection();
if (votePoll == null || themes.isEmpty()) {
send(player, "&cThere is nothing to vote for right now.");
return;
}
if (argument == null) {
sendThemeList(player, votePoll, themes);
buildArena.getVoteMenu().updateInventory(player);
return;
}
final int choice;
try {
choice = Integer.parseInt(argument);
} catch (NumberFormatException error) {
send(player, "&cCorrect Usage: /vote <theme number>");
sendThemeList(player, votePoll, themes);
return;
}
if (choice < 1 || choice > themes.size()) {
send(player, "&cInvalid theme!");
sendThemeList(player, votePoll, themes);
return;
}
final String theme = themes.get(choice - 1);
new MessageBuilder(votePoll.addVote(player, theme) ? "MENU_THEME_VOTE_SUCCESS" : "MENU_THEME_VOTE_ALREADY")
.asKey().player(player).value(theme).sendPlayer();
buildArena.getVoteMenu().updateInventory(player);
}
private void sendThemeList(Player player, VotePoll votePoll, List<String> themes) {
send(player, "&6Vote for a theme with /v #.");
send(player, "&6Theme choices up for voting:");
for (int i = 0; i < themes.size(); i++) {
final String theme = themes.get(i);
send(player, "&6&l" + (i + 1) + ". &6" + theme + " (&b" + votePoll.getVoteAmount(theme) + "&6 votes)");
}
}
private void send(Player player, String message) {
player.sendMessage(LEGACY_SERIALIZER.deserialize(plugin.getPluginMessagePrefix() + message));
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,247 +20,75 @@
package plugily.projects.buildbattle.commands.arguments;
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 net.md_5.bungee.api.chat.hover.content.Text;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.commands.TabCompletion;
import plugily.projects.buildbattle.commands.arguments.admin.ListArenasArgument;
import plugily.projects.buildbattle.commands.arguments.admin.ReloadArgument;
import plugily.projects.buildbattle.commands.arguments.admin.TeleportArgument;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.arena.GuessArena;
import plugily.projects.buildbattle.commands.arguments.admin.ThemeArgument;
import plugily.projects.buildbattle.commands.arguments.admin.arena.AddNpcArgument;
import plugily.projects.buildbattle.commands.arguments.admin.arena.DeleteArgument;
import plugily.projects.buildbattle.commands.arguments.admin.arena.ForceStartArguments;
import plugily.projects.buildbattle.commands.arguments.admin.arena.ForcePlayArgument;
import plugily.projects.buildbattle.commands.arguments.admin.arena.SetThemeArgument;
import plugily.projects.buildbattle.commands.arguments.admin.arena.StopArgument;
import plugily.projects.buildbattle.commands.arguments.admin.plot.AddPlotArgument;
import plugily.projects.buildbattle.commands.arguments.admin.plot.PlotWandArgument;
import plugily.projects.buildbattle.commands.arguments.admin.plot.RemovePlotArgument;
import plugily.projects.buildbattle.commands.arguments.admin.plot.SelectPlotArgument;
import plugily.projects.buildbattle.commands.arguments.admin.votes.VotesArgument;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import plugily.projects.buildbattle.commands.arguments.data.LabelData;
import plugily.projects.buildbattle.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.buildbattle.commands.arguments.game.ArenaSelectorArgument;
import plugily.projects.buildbattle.commands.arguments.game.CreateArgument;
import plugily.projects.buildbattle.commands.arguments.game.GuessArgument;
import plugily.projects.buildbattle.commands.arguments.game.JoinArguments;
import plugily.projects.buildbattle.commands.arguments.game.LeaderboardArgument;
import plugily.projects.buildbattle.commands.arguments.game.LeaveArgument;
import plugily.projects.buildbattle.commands.arguments.game.StatsArgument;
import plugily.projects.buildbattle.handlers.setup.SetupInventory;
import plugily.projects.buildbattle.utils.Debugger;
import plugily.projects.commonsbox.minecraft.compat.ServerVersion;
import plugily.projects.commonsbox.string.StringMatcher;
import plugily.projects.buildbattle.commands.arguments.game.JoinArgument;
import plugily.projects.buildbattle.commands.arguments.game.MenuArgument;
import plugily.projects.minigamesbox.api.arena.IPluginArena;
import plugily.projects.minigamesbox.classic.commands.arguments.PluginArgumentsRegistry;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Locale;
import java.util.stream.Collectors;
/**
* @author Plajer
* <p>
* Created at 03.12.2018
* <p>
* Created at 24.11.2018
*/
public class ArgumentsRegistry implements CommandExecutor {
public class ArgumentsRegistry extends PluginArgumentsRegistry {
private final Map<String, List<CommandArgument>> mappedArguments = new HashMap<>();
private final Main plugin;
public ArgumentsRegistry(Main plugin) {
public ArgumentsRegistry(Main plugin) {
this.plugin = plugin;
TabCompletion completion = new TabCompletion(this);
Optional.ofNullable(plugin.getCommand("buildbattle")).ifPresent(bb -> {
bb.setExecutor(this);
bb.setTabCompleter(completion);
});
Optional.ofNullable(plugin.getCommand("buildbattleadmin")).ifPresent(bba -> {
bba.setExecutor(this);
bba.setTabCompleter(completion);
});
super(plugin);
new AddNpcArgument(this);
new ForcePlayArgument(this);
new SetThemeArgument(this);
new AddPlotArgument(this);
new RemovePlotArgument(this);
new SelectPlotArgument(this);
new MenuArgument(this);
new GuessArgument(this);
new ThemeArgument(this);
// Replaces the bundled /bb join so a bare /bb join lists the lobbies.
new JoinArgument(this);
//register Build Battle basic arguments
new CreateArgument(this);
new JoinArguments(this);
new LeaderboardArgument(this);
new LeaveArgument(this);
new GuessArgument(this);
new StatsArgument(this);
new ArenaSelectorArgument(this);
//register Build Battle admin arguments
//arena related arguments
new AddNpcArgument(this);
new DeleteArgument(this);
new ForceStartArguments(this);
new ReloadArgument(this);
new SetThemeArgument(this);
new StopArgument(this);
new VotesArgument(this);
//plot related arguments
new AddPlotArgument(this);
new PlotWandArgument(this);
new RemovePlotArgument(this);
new SelectPlotArgument(this);
//other admin related arguments
new ListArenasArgument(this);
new TeleportArgument(this);
}
//todo complex
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) {
for(String mainCommand : mappedArguments.keySet()) {
if(cmd.getName().equalsIgnoreCase(mainCommand)) {
if(cmd.getName().equalsIgnoreCase("buildbattle")) {
if(args.length == 0 || args[0].equalsIgnoreCase("help")) {
sender.sendMessage(plugin.getChatManager().colorMessage("Commands.Main-Command.Header"));
sender.sendMessage(plugin.getChatManager().colorMessage("Commands.Main-Command.Description"));
if(sender.hasPermission("buildbattle.admin")) {
sender.sendMessage(plugin.getChatManager().colorMessage("Commands.Main-Command.Admin-Bonus-Description"));
}
sender.sendMessage(plugin.getChatManager().colorMessage("Commands.Main-Command.Footer"));
return true;
}
if(args.length > 1 && args[1].equalsIgnoreCase("edit")) {
if(args[1].equalsIgnoreCase("edit") || args[0].equalsIgnoreCase("create")) {
if(!checkSenderIsExecutorType(sender, CommandArgument.ExecutorType.PLAYER) || !hasPermission(sender, "buildbattle.admin.create")) {
return true;
}
BaseArena arena = ArenaRegistry.getArena(args[0]);
if(arena == null) {
sender.sendMessage(plugin.getChatManager().getPrefix() + plugin.getChatManager().colorMessage("Commands.No-Arena-Like-That"));
return true;
}
SetupInventory.sendProTip((Player) sender);
new SetupInventory(arena).openInventory((Player) sender);
return true;
}
}
}
if(cmd.getName().equalsIgnoreCase("buildbattleadmin") && (args.length == 0 || args[0].equalsIgnoreCase("help"))) {
if(!sender.hasPermission("buildbattle.admin")) {
return true;
}
sender.sendMessage(ChatColor.GREEN + " " + ChatColor.BOLD + "Build Battle " + ChatColor.GRAY + plugin.getDescription().getVersion());
sender.sendMessage(ChatColor.RED + " []" + ChatColor.GRAY + " = optional " + ChatColor.GOLD + "<>" + ChatColor.GRAY + " = required");
if(sender instanceof Player) {
sender.sendMessage(ChatColor.GRAY + "Hover command to see more, click command to suggest it.");
}
List<LabelData> data = mappedArguments.get("buildbattleadmin").stream().filter(arg -> arg instanceof LabeledCommandArgument)
.map(arg -> ((LabeledCommandArgument) arg).getLabelData()).collect(Collectors.toList());
data.add(new LabelData("/bb &6<arena>&f edit", "/bb <arena> edit",
"&7Edit existing arena\n&6Permission: &7buildbattle.admin.edit"));
data.addAll(mappedArguments.get("buildbattle").stream().filter(arg -> arg instanceof LabeledCommandArgument)
.map(arg -> ((LabeledCommandArgument) arg).getLabelData()).collect(Collectors.toList()));
for(LabelData labelData : data) {
if(sender instanceof Player) {
TextComponent component = new TextComponent(labelData.getText());
component.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, labelData.getCommand()));
// Backwards compatibility
if(ServerVersion.Version.isCurrentEqualOrHigher(ServerVersion.Version.v1_16_R1)) {
component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(labelData.getDescription())));
} else {
component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(labelData.getDescription())));
}
((Player) sender).spigot().sendMessage(component);
} else {
//more descriptive for console - split at \n to show only basic description
Debugger.sendConsoleMsg(labelData.getText() + " - " + labelData.getDescription().split("\n")[0]);
}
}
return true;
}
for(CommandArgument argument : mappedArguments.get(mainCommand)) {
if(argument.getArgumentName().equalsIgnoreCase(args[0])) {
for(String perm : argument.getPermissions()) {
if(perm.isEmpty() || hasPermission(sender, perm)) {
break;
}
//user has no permission to execute command
return true;
}
if(checkSenderIsExecutorType(sender, argument.getValidExecutors())) {
argument.execute(sender, args);
}
//return true even if sender is not good executor or hasn't got permission
return true;
}
}
//sending did you mean help
List<StringMatcher.Match> matches = StringMatcher.match(args[0], mappedArguments.get(cmd.getName().toLowerCase()).stream().map(CommandArgument::getArgumentName).collect(Collectors.toList()));
if(!matches.isEmpty()) {
sender.sendMessage(plugin.getChatManager().colorMessage("Commands.Did-You-Mean").replace("%command%", label + " " + matches.get(0).getMatch()));
return true;
}
}
}
return false;
}
private boolean checkSenderIsExecutorType(CommandSender sender, CommandArgument.ExecutorType type) {
switch(type) {
case BOTH:
return sender instanceof ConsoleCommandSender || sender instanceof Player;
case CONSOLE:
return sender instanceof ConsoleCommandSender;
case PLAYER:
if(sender instanceof Player) {
return true;
@Override
public List<IPluginArena> getSpecificFilteredArenas(List<IPluginArena> arenas, String filter) {
switch (filter.toLowerCase(Locale.ENGLISH)) {
case "gtb":
case "guessthebuild":
case "guess_the_build":
return arenas.stream().filter(GuessArena.class::isInstance).collect(Collectors.toList());
case "team":
return arenas.stream().filter(BuildArena.class::isInstance)
.filter(arena -> ((BuildArena) arena).getArenaType().equals(BaseArena.ArenaType.TEAM))
.collect(Collectors.toList());
case "classic":
case "solo":
return arenas.stream().filter(BuildArena.class::isInstance)
.filter(arena -> ((BuildArena) arena).getArenaType().equals(BaseArena.ArenaType.SOLO))
.collect(Collectors.toList());
case "build":
default:
return arenas.stream().filter(BuildArena.class::isInstance).collect(Collectors.toList());
}
sender.sendMessage(plugin.getChatManager().colorMessage("Commands.Only-By-Player"));
return false;
default:
return false;
}
}
/**
* Maps new argument to the main command
*
* @param mainCommand mother command ex. /mm
* @param argument argument to map ex. leave (for /mm leave)
*/
public void mapArgument(String mainCommand, CommandArgument argument) {
List<CommandArgument> args = mappedArguments.getOrDefault(mainCommand, new ArrayList<>());
args.add(argument);
mappedArguments.put(mainCommand, args);
}
public boolean hasPermission(CommandSender sender, String perm) {
if(sender.hasPermission(perm)) {
return true;
}
sender.sendMessage(plugin.getChatManager().getPrefix() + plugin.getChatManager().colorMessage("Commands.No-Permission"));
return false;
}
public Map<String, List<CommandArgument>> getMappedArguments() {
return mappedArguments;
}
public Main getPlugin() {
return plugin;
}
}
@@ -1,60 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.commands.arguments.admin;
import org.bukkit.command.CommandSender;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import plugily.projects.buildbattle.commands.arguments.data.LabelData;
import plugily.projects.buildbattle.commands.arguments.data.LabeledCommandArgument;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class ListArenasArgument {
public ListArenasArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("list", "buildbattle.admin.list", CommandArgument.ExecutorType.BOTH,
new LabelData("/bba list", "/bba list",
"&7Shows list with all loaded arenas\n&6Permission: &7buildbattle.admin.list")) {
@Override
public void execute(CommandSender sender, String[] args) {
sender.sendMessage(registry.getPlugin().getChatManager().colorMessage("Commands.Admin-Commands.List-Command.Header"));
if(ArenaRegistry.getArenas().size() == 0) {
sender.sendMessage(registry.getPlugin().getChatManager().colorMessage("Commands.Admin-Commands.List-Command.No-Arenas"));
sender.sendMessage(registry.getPlugin().getChatManager().colorRawMessage("&e&lTIP: &7You can get free maps with configs at our wiki! Just head to https://wiki.plugily.xyz/buildbattle/setup/maps"));
return;
}
for(BaseArena arena : ArenaRegistry.getArenas()) {
sender.sendMessage(registry.getPlugin().getChatManager().colorMessage("Commands.Admin-Commands.List-Command.Format").replace("%arena%", arena.getID())
.replace("%status%", arena.getArenaState().getPlaceholder()).replace("%players%", Integer.toString(arena.getPlayers().size()))
.replace("%maxplayers%", Integer.toString(arena.getMaximumPlayers())));
}
}
});
}
}
@@ -1,88 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.commands.arguments.admin;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import plugily.projects.commonsbox.minecraft.serialization.InventorySerializer;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.arena.ArenaManager;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import plugily.projects.buildbattle.commands.arguments.data.LabelData;
import plugily.projects.buildbattle.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.buildbattle.handlers.language.LanguageManager;
import java.util.HashSet;
import java.util.Set;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class ReloadArgument {
private final Set<CommandSender> confirmations = new HashSet<>();
public ReloadArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("reload", "buildbattle.admin.reload", CommandArgument.ExecutorType.BOTH,
new LabelData("/bba reload", "/bba reload", "&7Reload all game arenas and configuration files\n&7&lThey will be stopped!\n&6Permission: &7buildbattle.admin.reload")) {
@Override
public void execute(CommandSender sender, String[] args) {
if(!confirmations.contains(sender)) {
confirmations.add(sender);
Bukkit.getScheduler().runTaskLater(registry.getPlugin(), () -> confirmations.remove(sender), 20 * 10);
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix()
+ registry.getPlugin().getChatManager().colorRawMessage("&cAre you sure you want to do this action? Type the command again &6within 10 seconds &cto confirm!"));
return;
}
confirmations.remove(sender);
registry.getPlugin().reloadConfig();
LanguageManager.reloadConfig();
for(BaseArena arena : ArenaRegistry.getArenas()) {
for(Player player : arena.getPlayers()) {
arena.doBarAction(BaseArena.BarAction.REMOVE, player);
arena.teleportToEndLocation(player);
if(registry.getPlugin().getConfigPreferences().getOption(ConfigPreferences.Option.INVENTORY_MANAGER_ENABLED)) {
InventorySerializer.loadInventory(registry.getPlugin(), player);
} else {
player.getInventory().clear();
player.getInventory().setArmorContents(null);
player.getActivePotionEffects().forEach(pe -> player.removePotionEffect(pe.getType()));
}
}
ArenaManager.stopGame(true, arena);
}
registry.getPlugin().getConfigPreferences().loadOptions();
ArenaRegistry.registerArenas();
sender.sendMessage(ChatColor.GREEN + "Plugin reloaded!");
}
});
}
}
@@ -1,111 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.commands.arguments.admin;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import plugily.projects.buildbattle.commands.arguments.data.LabelData;
import plugily.projects.buildbattle.commands.arguments.data.LabeledCommandArgument;
import java.util.Arrays;
/**
* @author Tigerpanzer_02
* <p>
* Created at 14.03.2021
*/
public class TeleportArgument {
public TeleportArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("tp", "buildbattle.admin.teleport", CommandArgument.ExecutorType.PLAYER,
new LabelData("/bba tp &6<arena> <location type>", "/bba tp <arena> <location>",
"&7Teleport you to provided arena location\n&7Valid locations:\n&7• LOBBY - lobby location\n&7• START - starting location\n"
+ "&7• END - ending location\n&6Permission: &7buildbattle.admin.teleport")) {
@Override
public void execute(CommandSender sender, String[] args) {
if(args.length == 1) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.Type-Arena-Name"));
return;
}
if(args.length == 2) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + ChatColor.RED + "Please type location type: " + Arrays.toString(LocationType.values()).replace("[", "").replace("]", ""));
return;
}
Player player = (Player) sender;
LocationType type;
try {
type = LocationType.valueOf(args[2].toUpperCase());
} catch(IllegalArgumentException e) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + ChatColor.RED + "Please type location type: " + Arrays.toString(LocationType.values()).replace("[", "").replace("]", ""));
return;
}
for(BaseArena arena : ArenaRegistry.getArenas()) {
if(arena.getID().equalsIgnoreCase(args[1])) {
teleport(player, arena, type);
break;
}
}
}
});
}
private void teleport(Player player, BaseArena arena, LocationType locationType) {
switch(locationType) {
case LOBBY:
org.bukkit.Location lobby = arena.getLobbyLocation();
if(lobby == null) {
player.sendMessage(ChatColor.RED + "Lobby location isn't set for this arena!");
return;
}
player.teleport(lobby);
player.sendMessage(ChatColor.GRAY + "Teleported to LOBBY location from arena " + arena.getID());
break;
case START:
if(arena.getPlotManager().getPlots().isEmpty()) {
player.sendMessage(ChatColor.RED + "Start location isn't set for this arena!");
return;
}
player.teleport(arena.getPlotManager().getPlots().get(0).getTeleportLocation());
player.sendMessage(ChatColor.GRAY + "Teleported to START location from arena " + arena.getID());
break;
case END:
if(arena.getEndLocation() == null) {
player.sendMessage(ChatColor.RED + "End location isn't set for this arena!");
return;
}
arena.teleportToEndLocation(player);
player.sendMessage(ChatColor.GRAY + "Teleported to END location from arena " + arena.getID());
break;
default:
break; //o.o
}
}
public enum LocationType {
LOBBY, END, START //todo PLOT
}
}
@@ -0,0 +1,193 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.commands.arguments.admin;
import java.util.Locale;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.command.CommandSender;
import plugily.projects.buildbattle.Main;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.handlers.themes.ThemeManager;
import plugily.projects.minigamesbox.classic.commands.arguments.data.CommandArgument;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabelData;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
public final class ThemeArgument {
private String printGameTypes() {
StringBuilder stringBuilder = new StringBuilder();
int length = ThemeManager.GameThemes.VALUES.length;
for (int i = 0; i < length; i++) {
stringBuilder.append(
ThemeManager.GameThemes.VALUES[i].strip.toLowerCase(Locale.ENGLISH) + (i + 1 < length ? ", " : ""));
}
return stringBuilder.toString();
}
public ThemeArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("theme", "buildbattle.admin.theme",
CommandArgument.ExecutorType.PLAYER,
new LabelData("/bba theme &c[add/remove] [gameType] [theme]", "/bba theme",
"&7Theme commands to add or remove themes for the specified game type\n&6Permission: &7buildbattle.admin.theme"))
{
@Override
public void execute(CommandSender sender, String[] args) {
if (args.length < 4) {
new MessageBuilder("COMMANDS_WRONG_USAGE").asKey().value(
"/" + registry.getPlugin().getCommandAdminPrefix() + " &c[add/remove] [gameType] [theme]")
.send(sender);
return;
}
String gameType = args[2];
ThemeManager.GameThemes theme = null;
for (ThemeManager.GameThemes gameTheme : ThemeManager.GameThemes.VALUES) {
if (gameTheme.strip.equalsIgnoreCase(gameType)) {
theme = gameTheme;
break;
}
}
if (theme == null) {
new MessageBuilder("&cThere is no game type with this name. Possible types: " + printGameTypes())
.prefix().send(sender);
return;
}
String themeName = PlainTextComponentSerializer.plainText()
.serialize(LegacyComponentSerializer.legacySection().deserialize(args[3]));
ThemeManager themeManager = ((Main) registry.getPlugin()).getThemeManager();
switch (args[1].toLowerCase(Locale.ENGLISH)) {
case "add":
if (themeManager.isThemeBlacklisted(themeName)) {
new MessageBuilder("COMMANDS_THEME_BLACKLISTED").asKey().prefix().send(sender);
return;
}
if (themeManager.getThemes(theme).contains(themeName)) {
new MessageBuilder("&cThe given theme already exists.").prefix().send(sender);
return;
}
switch (theme) {
case SOLO:
case CLASSIC:
themeManager.classicThemes.add(themeName);
break;
case TEAM:
case TEAMS:
themeManager.teamsThemes.add(themeName);
break;
case GUESS_THE_BUILD_EASY:
themeManager.GTBThemesEasy.add(themeName);
break;
case GUESS_THE_BUILD_MEDIUM:
themeManager.GTBThemesMedium.add(themeName);
break;
case GUESS_THE_BUILD_HARD:
themeManager.GTBThemesHard.add(themeName);
break;
default:
return;
}
themeManager.loadThemes(true);
themeManager.saveThemesToConfig();
break;
case "remove":
boolean contained = false;
switch (theme) {
case SOLO:
case CLASSIC:
contained = themeManager.classicThemes.remove(themeName);
break;
case TEAM:
case TEAMS:
contained = themeManager.teamsThemes.remove(themeName);
break;
case GUESS_THE_BUILD_EASY:
contained = themeManager.GTBThemesEasy.remove(themeName);
break;
case GUESS_THE_BUILD_MEDIUM:
contained = themeManager.GTBThemesMedium.remove(themeName);
break;
case GUESS_THE_BUILD_HARD:
contained = themeManager.GTBThemesHard.remove(themeName);
break;
default:
return;
}
if (!contained) {
new MessageBuilder("&cThe given theme doesn't exists.").prefix().send(sender);
return;
}
themeManager.loadThemes(true);
themeManager.saveThemesToConfig();
break;
default:
break;
}
}
});
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,34 +26,48 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import plugily.projects.buildbattle.commands.arguments.data.LabelData;
import plugily.projects.buildbattle.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.classic.commands.arguments.data.CommandArgument;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabelData;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
* <p>
* Created at 11.01.2019
*/
public class AddNpcArgument {
public AddNpcArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("addnpc", "buildbattle.admin.addnpc", CommandArgument.ExecutorType.PLAYER,
new LabelData("/bba addnpc &6<arena>", "/bba addnpc <arena>",
"&7Deletes specified arena\n&6Permission: &7buildbattle.admin.addnpc")) {
@Override
public void execute(CommandSender sender, String[] args) {
if(registry.getPlugin().getServer().getPluginManager().isPluginEnabled("Citizens")) {
NPC npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.VILLAGER, registry.getPlugin().getChatManager().colorMessage("In-Game.NPC.Floor-Change-NPC-Name"));
npc.spawn(((Player) sender).getLocation());
npc.setProtected(true);
npc.setName(registry.getPlugin().getChatManager().colorMessage("In-Game.NPC.Floor-Change-NPC-Name"));
sender.sendMessage(registry.getPlugin().getChatManager().colorMessage("In-Game.NPC.NPC-Created"));
} else {
sender.sendMessage(registry.getPlugin().getChatManager().colorMessage("In-Game.NPC.Install-Citizens"));
}
}
});
}
public AddNpcArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin",
new LabeledCommandArgument("addnpc", "buildbattle.admin.addnpc", CommandArgument.ExecutorType.PLAYER,
new LabelData("/bba addnpc", "/bba addnpc",
"&7Deletes specified arena\n&6Permission: &7buildbattle.admin.addnpc"))
{
@Override
public void execute(CommandSender sender, String[] args) {
if (registry.getPlugin().getServer().getPluginManager().isPluginEnabled("Citizens")) {
NPC npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.VILLAGER,
new MessageBuilder("IN_GAME_MESSAGES_PLOT_NPC_NAME").asKey().build());
npc.spawn(((Player) sender).getLocation());
npc.setProtected(true);
npc.setName(new MessageBuilder("IN_GAME_MESSAGES_PLOT_NPC_NAME").asKey().build());
new MessageBuilder("IN_GAME_MESSAGES_PLOT_NPC_CREATED").asKey().send(sender);
} else {
new MessageBuilder("IN_GAME_MESSAGES_PLOT_NPC_CITIZENS").asKey().send(sender);
}
}
});
}
}
@@ -1,80 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.commands.arguments.admin.arena;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import plugily.projects.commonsbox.minecraft.configuration.ConfigUtils;
import plugily.projects.buildbattle.arena.ArenaManager;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import plugily.projects.buildbattle.commands.arguments.data.LabelData;
import plugily.projects.buildbattle.commands.arguments.data.LabeledCommandArgument;
import java.util.HashSet;
import java.util.Set;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class DeleteArgument {
private final Set<CommandSender> confirmations = new HashSet<>();
public DeleteArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("delete", "buildbattle.admin.delete", CommandArgument.ExecutorType.PLAYER,
new LabelData("/bba delete &6<arena>", "/bba delete <arena>",
"&7Deletes specified arena\n&6Permission: &7buildbattle.admin.delete")) {
@Override
public void execute(CommandSender sender, String[] args) {
if(args.length == 1) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.Type-Arena-Name"));
return;
}
BaseArena arena = ArenaRegistry.getArena(args[1]);
if(arena == null) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.No-Arena-Like-That"));
return;
}
if(!confirmations.contains(sender)) {
confirmations.add(sender);
Bukkit.getScheduler().runTaskLater(registry.getPlugin(), () -> confirmations.remove(sender), 20 * 10);
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix()
+ registry.getPlugin().getChatManager().colorRawMessage("&cAre you sure you want to do this action? Type the command again &6within 10 seconds &cto confirm!"));
return;
}
confirmations.remove(sender);
ArenaManager.stopGame(false, arena);
FileConfiguration config = ConfigUtils.getConfig(registry.getPlugin(), "arenas");
config.set("instances." + args[1], null);
ConfigUtils.saveConfig(registry.getPlugin(), config, "arenas");
ArenaRegistry.unregisterArena(arena);
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.Removed-Game-Instance"));
}
});
}
}
@@ -0,0 +1,148 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.commands.arguments.admin.arena;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.classic.commands.arguments.data.CommandArgument;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabelData;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import java.util.StringJoiner;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class ForcePlayArgument {
public ForcePlayArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("forceplay", "buildbattle.admin.forceplay",
CommandArgument.ExecutorType.BOTH,
new LabelData("/bba forceplay <arena> <theme>", "/bba forceplay <arena> <theme>",
"&7Start a arena by command \n&6Permission: &7buildbattle.admin.forceplay\n&cNOT FOR PRODUCTION!"))
{
@Override
public void execute(CommandSender sender, String[] args) {
if (args.length == 1) {
new MessageBuilder("&cPlease type arena theme!").prefix().send(sender);
return;
}
BaseArena arena;
int themeArgStart = 1;
if (!(sender instanceof Player)) {
arena = (BaseArena) registry.getPlugin().getArenaRegistry().getArena(args[1]);
if (args.length == 2 && arena != null) {
BaseArena finalArena = arena;
Bukkit.getOnlinePlayers().forEach(player -> {
registry.getPlugin().getArenaManager().joinAttempt(player, finalArena);
});
arena.setForceStart(true);
return;
}
themeArgStart = 2;
} else {
arena = (BaseArena) registry.getPlugin().getArenaRegistry().getArena((Player) sender);
if (arena == null) {
arena = (BaseArena) registry.getPlugin().getArenaRegistry().getArena(args[1]);
}
}
if (arena == null) {
new MessageBuilder("COMMANDS_NOT_PLAYING").asKey().send(sender);
return;
}
if (!(arena instanceof BuildArena)) {
new MessageBuilder("&cCan't set theme on this arena type!").prefix().send(sender);
return;
}
StringJoiner themeName = new StringJoiner(" ");
for (int i = themeArgStart; i < args.length; i++)
themeName.add(args[i]);
if (arena.getArenaInGameState() == BaseArena.ArenaInGameState.BUILD_TIME
|| arena.getArenaState() == IArenaState.WAITING_FOR_PLAYERS
|| arena.getArenaState() == IArenaState.STARTING
|| arena.getArenaState() == IArenaState.FULL_GAME
|| arena.getArenaInGameState() == BaseArena.ArenaInGameState.THEME_VOTING)
{
if (arena.getPlugin().getThemeManager().isThemeBlacklisted(themeName.toString())) {
new MessageBuilder("COMMANDS_THEME_BLACKLISTED").asKey().prefix().send(sender);
return;
}
BaseArena finalArena1 = arena;
Bukkit.getOnlinePlayers().forEach(player -> {
registry.getPlugin().getArenaManager().joinAttempt(player, finalArena1);
});
arena.setForceStart(true);
arena.setTheme(themeName.toString());
new MessageBuilder("IN_GAME_MESSAGES_ADMIN_CHANGED_THEME").asKey().prefix()
.value(themeName.toString()).arena(arena).sendArena();
} else {
new MessageBuilder("&cWrong state to force theme!").prefix().send(sender);
}
}
});
}
}
@@ -1,53 +0,0 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package plugily.projects.buildbattle.commands.arguments.admin.arena;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.arena.ArenaUtils;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import plugily.projects.buildbattle.commands.arguments.data.LabelData;
import plugily.projects.buildbattle.commands.arguments.data.LabeledCommandArgument;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
*/
public class ForceStartArguments {
public ForceStartArguments(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("forcestart", "buildbattle.admin.forcestart", CommandArgument.ExecutorType.PLAYER,
new LabelData("/bba forcestart &c[theme]", "/bba forcestart",
"&7Force starts arena you're in\n&6Permission: &7buildbattle.admin.forcestart")) {
@Override
public void execute(CommandSender sender, String[] args) {
if(args.length == 2 && !sender.hasPermission("buildbattle.admin.forcestart.theme")) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.No-Permission"));
return;
}
ArenaUtils.arenaForceStart((Player) sender, args.length == 2 ? args[1] : "");
}
});
}
}
@@ -1,7 +1,7 @@
/*
*
* BuildBattle - Ultimate building competition minigame
* Copyright (C) 2021 Plugily Projects - maintained by Tigerpanzer_02, 2Wild4You and contributors
* Copyright (C) 2022 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,60 +22,109 @@ package plugily.projects.buildbattle.commands.arguments.admin.arena;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import plugily.projects.buildbattle.ConfigPreferences;
import plugily.projects.buildbattle.arena.ArenaRegistry;
import plugily.projects.buildbattle.arena.ArenaState;
import plugily.projects.buildbattle.arena.impl.BaseArena;
import plugily.projects.buildbattle.arena.impl.SoloArena;
import plugily.projects.buildbattle.arena.BaseArena;
import plugily.projects.buildbattle.arena.BuildArena;
import plugily.projects.buildbattle.commands.arguments.ArgumentsRegistry;
import plugily.projects.buildbattle.commands.arguments.data.CommandArgument;
import plugily.projects.buildbattle.commands.arguments.data.LabelData;
import plugily.projects.buildbattle.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.api.arena.IArenaState;
import plugily.projects.minigamesbox.classic.commands.arguments.data.CommandArgument;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabelData;
import plugily.projects.minigamesbox.classic.commands.arguments.data.LabeledCommandArgument;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import java.util.StringJoiner;
/**
* @author Plajer
* <p>
* Created at 11.01.2019
* <p>
* Created at 11.01.2019
*/
public class SetThemeArgument {
public SetThemeArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("settheme", "buildbattle.admin.settheme", CommandArgument.ExecutorType.PLAYER,
new LabelData("/bba settheme &6<theme>", "/bba settheme",
"&7Set new arena theme\n&6Permission: &7buildbattle.admin.settheme\n&6You can set arena theme only when it started\n&6and only for 20 seconds after start!")) {
@Override
public void execute(CommandSender sender, String[] args) {
BaseArena arena = ArenaRegistry.getArena((Player) sender);
if(arena == null) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.No-Playing"));
return;
}
if(!(arena instanceof SoloArena)) {
//todo translatable
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorRawMessage("&cCan't set theme on this arena type!"));
return;
}
if(args.length == 1) {
//todo translatable
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorRawMessage("&cPlease type arena theme!"));
return;
}
if(arena.getArenaState() == ArenaState.IN_GAME && registry.getPlugin().getConfigPreferences().getTimer(ConfigPreferences.TimerType.BUILD, arena) - arena.getTimer() <= 20) {
if(registry.getPlugin().getConfigPreferences().isThemeBlacklisted(args[1].toLowerCase())) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.Admin-Commands.Theme-Blacklisted"));
return;
}
arena.setTheme(args[1]);
registry.getPlugin().getChatManager().broadcast(arena, registry.getPlugin().getChatManager().colorMessage("In-Game.Messages.Admin-Messages.Changed-Theme").replace("%THEME%", args[1]));
} else {
if(arena.getArenaState() == ArenaState.STARTING) {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.Wait-For-Start"));
} else {
sender.sendMessage(registry.getPlugin().getChatManager().getPrefix() + registry.getPlugin().getChatManager().colorMessage("Commands.Arena-Started"));
}
}
}
});
}
public SetThemeArgument(ArgumentsRegistry registry) {
registry.mapArgument("buildbattleadmin", new LabeledCommandArgument("settheme", "buildbattle.admin.settheme",
CommandArgument.ExecutorType.BOTH,
new LabelData("/bba settheme &6<theme>",
"/bba settheme <theme> || Console /bba settheme <arena> <theme>",
"&7Set new arena theme\n&6Permission: &7buildbattle.admin.settheme\n&6You can set arena theme only when it started\n&6and only for 20 seconds after start!"))
{
@Override
public void execute(CommandSender sender, String[] args) {
if (args.length == 1) {
// todo translatable
new MessageBuilder("&cPlease type arena theme!").prefix().send(sender);
return;
}
BaseArena arena;
int themeArgStart = 1;
if (!(sender instanceof Player)) {
if (args.length == 2) {
// todo translatable
new MessageBuilder("&cPlease type arena name!").prefix().send(sender);
return;
}
arena = (BaseArena) registry.getPlugin().getArenaRegistry().getArena(args[1]);
themeArgStart = 2;
} else {
arena = (BaseArena) registry.getPlugin().getArenaRegistry().getArena((Player) sender);
}
if (arena == null) {
new MessageBuilder("COMMANDS_NOT_PLAYING").asKey().send(sender);
return;
}
if (!(arena instanceof BuildArena)) {
// todo translatable
new MessageBuilder("&cCan't set theme on this arena type!").prefix().send(sender);
return;
}
StringJoiner themeName = new StringJoiner(" ");
for (int i = themeArgStart; i < args.length; i++)
themeName.add(args[i]);
if (arena.getArenaInGameState() == BaseArena.ArenaInGameState.BUILD_TIME
|| arena.getArenaState() == IArenaState.STARTING)
{
if (arena.getPlugin().getThemeManager().isThemeBlacklisted(themeName.toString())) {
new MessageBuilder("COMMANDS_THEME_BLACKLISTED").asKey().prefix().send(sender);
return;
}
arena.setTheme(themeName.toString());
new MessageBuilder("IN_GAME_MESSAGES_ADMIN_CHANGED_THEME").asKey().prefix()
.value(themeName.toString()).arena(arena).sendArena();
} else {
new MessageBuilder("&cWrong state to force theme!").prefix().send(sender);
}
}
});
}
}
Loaded 100 of 272 files, more files were not shown because too many files have changed in this diff. Show more