├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── common ├── pom.xml └── src │ └── main │ └── java │ └── ru │ └── beykerykt │ └── lightapi │ ├── LightType.java │ ├── chunks │ └── ChunkInfo.java │ ├── server │ └── nms │ │ ├── INMSHandler.java │ │ └── NmsHandlerBase.java │ └── utils │ ├── Debug.java │ └── Utils.java ├── nms ├── v1_10_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_10_R1.java ├── v1_11_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_11_R1.java ├── v1_12_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_12_R1.java ├── v1_13_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_13_R1.java ├── v1_13_R2 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_13_R2.java ├── v1_14_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_14_R1.java ├── v1_15_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_15_R1.java ├── v1_16_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_16_R1.java ├── v1_16_R2 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_16_R2.java ├── v1_16_R3 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_16_R3.java ├── v1_17_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_17_R1.java ├── v1_8_R3 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_8_R3.java ├── v1_9_R1 │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ └── server │ │ └── nms │ │ └── craftbukkit │ │ └── CraftBukkit_v1_9_R1.java └── v1_9_R2 │ ├── pom.xml │ └── src │ └── main │ └── java │ └── ru │ └── beykerykt │ └── lightapi │ └── server │ └── nms │ └── craftbukkit │ └── CraftBukkit_v1_9_R2.java ├── others ├── LIGHT_API_LOGO.png ├── LIGHT_API_LOGO.psd ├── light_api_logo_version_2.png ├── light_api_logo_version_2.psd ├── light_api_logo_version_3.png ├── light_api_logo_version_3.psd └── torch.png ├── plugin ├── pom.xml └── src │ └── main │ ├── java │ └── ru │ │ └── beykerykt │ │ └── lightapi │ │ ├── LightAPI.java │ │ ├── chunks │ │ ├── ChunkLocation.java │ │ └── ChunkUpdateInfo.java │ │ ├── events │ │ ├── DeleteLightEvent.java │ │ ├── SetLightEvent.java │ │ └── UpdateChunkEvent.java │ │ ├── request │ │ └── RequestSteamMachine.java │ │ ├── server │ │ ├── ServerModInfo.java │ │ └── ServerModManager.java │ │ ├── updater │ │ ├── Response.java │ │ ├── UpdateType.java │ │ ├── Updater.java │ │ ├── UpdaterRunnable.java │ │ └── Version.java │ │ └── utils │ │ ├── BungeeChatHelperClass.java │ │ └── Metrics_bStats.java │ └── resources │ ├── config.yml │ └── plugin.yml └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Eclipse files 4 | /bin 5 | .classpath 6 | 7 | # Mobile Tools for Java (J2ME) 8 | .mtj.tmp/ 9 | 10 | # Package Files # 11 | *.jar 12 | *.war 13 | *.ear 14 | 15 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 16 | hs_err_pid* 17 | 18 | .idea/ 19 | *.iml 20 | 21 | target/ 22 | 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | * [2017-08-13] [BeYkeRYkt] format 2 | * [2017-08-12] [BeYkeRYkt] Revert "common: import ThreadHotplug" 3 | * [2017-08-12] [BeYkeRYkt] add missings return 4 | * [2017-08-12] [BeYkeRYkt] common: import ThreadHotplug 5 | * [2017-07-31] [BeYkeRYkt] common: implement 'servermod' exceptions 6 | * [2017-07-31] [BeYkeRYkt] nms: fix building 7 | * [2017-07-31] [Vladimir Mikhaylov] Merge pull request #9 from Dereku/CraftBukkit_v1_12_R1 8 | |\ 9 | | * [2017-07-09] [Dereku] 1.12 support 10 | |/ 11 | * [2017-04-13] [Vladimir Mikhaylov] Merge pull request #6 from kh498/3.0 12 | |\ 13 | | * [2017-04-13] [kh498] Use the squared distance to increase performance 14 | |/ 15 | * [2016-12-09] [BeYkeRYkt] Update README.md 16 | * [2016-12-08] [BeYkeRYkt] Update logo 17 | * [2016-12-04] [BeYkeRYkt] request: separate update flags 18 | * [2016-12-04] [BeYkeRYkt] Merge pull request #4 from Nashoba24/3.0 19 | |\ 20 | | * [2016-11-18] [Nashoba24] Support 1.11 21 | |/ 22 | * [2016-10-21] [BeYkeRYkt] request: remove unnecessary runnable 23 | * [2016-08-17] [BeYkeRYkt] Bump version! 24 | * [2016-08-17] [BeYkeRYkt] events: fix forgotten isCancelled 25 | * [2016-08-17] [BeYkeRYkt] bungee: move method to BungeeChatHelper 26 | * [2016-08-07] [BeYkeRYkt] add missing license message 27 | * [2016-08-07] [BeYkeRYkt] Bump version ! 28 | * [2016-08-07] [BeYkeRYkt] LightAPI: fix error for CraftBukkit builds 29 | * [2016-08-07] [BeYkeRYkt] utils: add BungeeChatHelper for fix CraftBukkit error 30 | * [2016-08-07] [BeYkeRYkt] smm: add method for check BungeeChatAPI 31 | * [2016-08-07] [BeYkeRYkt] Update README.md 32 | * [2016-08-07] [BeYkeRYkt] misc: upload new logo v2 33 | * [2016-07-07] [BeYkeRYkt] Bump version 34 | * [2016-07-07] [BeYkeRYkt] cmd: add code for console 35 | * [2016-07-06] [BeYkeRYkt] Bump version (according with Semantic versioning) 36 | * [2016-07-06] [BeYkeRYkt] updater: add info about repository 37 | * [2016-07-06] [BeYkeRYkt] updater: add view changelog option 38 | * [2016-07-06] [BeYkeRYkt] smm: remove unused code 39 | * [2016-07-06] [BeYkeRYkt] Fix License 40 | * [2016-07-06] [BeYkeRYkt] Update README.md 41 | * [2016-07-06] [BeYkeRYkt] Add logo in README.md 42 | * [2016-07-06] [BeYkeRYkt] Bump version 43 | * [2016-07-06] [BeYkeRYkt] cmd: add server name information 44 | * [2016-07-06] [BeYkeRYkt] Delete CHANGELOG.md ? 45 | * [2016-07-06] [BeYkeRYkt] Revert "cmd: add enableUpdater checker" 46 | * [2016-07-06] [BeYkeRYkt] cmd: add enableUpdater checker 47 | * [2016-07-06] [BeYkeRYkt] LightAPI: add commands, update updater 48 | * [2016-07-06] [BeYkeRYkt] Revert "request: remove async runnable from async thread" 49 | * [2016-07-06] [BeYkeRYkt] add license header 50 | * [2016-07-06] [BeYkeRYkt] license: 2016 ? no ? 51 | * [2016-07-06] [BeYkeRYkt] request: remove async runnable from async thread 52 | * [2016-07-06] [BeYkeRYkt] cmd: init commands 53 | * [2016-06-23] [BeYkeRYkt] Bump version 54 | * [2016-06-23] [BeYkeRYkt] request: fix java.lang.InterruptedException 55 | * [2016-06-23] [BeYkeRYkt] request: improvement async execute 56 | * [2016-06-23] [BeYkeRYkt] updater: add warning message 57 | * [2016-06-23] [BeYkeRYkt] LightAPI: I think you do not have a potato pc :) 58 | * [2016-06-23] [BeYkeRYkt] updater: introduce update type information 59 | * [2016-06-22] [BeYkeRYkt] Bump version 60 | * [2016-06-22] [BeYkeRYkt] request: improvement chunk sending 61 | * [2016-06-22] [BeYkeRYkt] LightAPI: Fix unused configuration parameters 62 | * [2016-06-21] [BeYkeRYkt] LightAPI: fix incorrect x,z 63 | * [2016-06-21] [BeYkeRYkt] LightAPI: fix updateChunk() 64 | * [2016-06-21] [BeYkeRYkt] LightAPI: correct collectChunks with location and add missing setReceivers() 65 | * [2016-06-21] [BeYkeRYkt] smm: rename "support" to "handler" 66 | * [2016-06-21] [BeYkeRYkt] LightAPI: add methods for single update chunk 67 | * [2016-06-21] [BeYkeRYkt] LightAPI: now updateChunks(location) updates the nearest beside chunks 68 | * [2016-06-21] [BeYkeRYkt] LightAPI: rename updateChunks() to updateChunk() 69 | * [2016-06-20] [BeYkeRYkt] Release 3.0.0 [NEED MORE TEST!] 70 | * [2016-06-20] [BeYkeRYkt] config: add "enable-updater" line 71 | * [2016-06-20] [BeYkeRYkt] nms: add missing v1_9_R1 72 | * [2016-06-20] [BeYkeRYkt] Format code 73 | * [2016-06-20] [BeYkeRYkt] main: Update LightAPI 74 | * [2016-06-20] [BeYkeRYkt] events: introduce events from 1.0 75 | * [2016-06-20] [BeYkeRYkt] nms: init new nms handlers 76 | * [2016-06-20] [BeYkeRYkt] chunk: now we can set y-height 77 | * [2016-06-20] [BeYkeRYkt] request: remove unused code 78 | * [2016-06-20] [BeYkeRYkt] nms: remove handler for replacing class 79 | * [2016-06-20] [BeYkeRYkt] smm: fix to display properly initialize text 80 | * [2016-06-20] [BeYkeRYkt] Revert "build: introduce build information" 81 | * [2016-06-19] [BeYkeRYkt] nms: update chunk field for v1_9_R2 82 | * [2016-06-19] [BeYkeRYkt] main: Update LightAPI 83 | * [2016-06-19] [BeYkeRYkt] Format code 84 | * [2016-06-19] [BeYkeRYkt] request: sending chunks after queue 85 | * [2016-06-19] [BeYkeRYkt] nms: fix for sending chunks 86 | * [2016-06-19] [BeYkeRYkt] nms: added support craftbukkit 1.9_R2 87 | * [2016-06-19] [BeYkeRYkt] request: update to 3.0 88 | * [2016-06-19] [BeYkeRYkt] smm: fix extends class 89 | * [2016-06-19] [BeYkeRYkt] smm: fix extends class 90 | * [2016-06-19] [BeYkeRYkt] nms: update methods for new ChunkInfo 91 | * [2016-06-19] [BeYkeRYkt] chunk: add Y-height information 92 | * [2016-06-19] [BeYkeRYkt] build: introduce build information 93 | * [2016-06-19] [BeYkeRYkt] request: init request death machine 94 | * [2016-06-19] [BeYkeRYkt] smm: init hashmap ? 95 | * [2016-06-19] [BeYkeRYkt] smm: init nms 96 | * [2016-06-19] [BeYkeRYkt] smm: rename sm 2 smm 97 | * [2016-06-19] [BeYkeRYkt] chunk: init ChunkInfo 98 | * [2016-06-19] [BeYkeRYkt] chunk: init ChunkCache 99 | * [2016-06-19] [BeYkeRYkt] nms: add methods for sending chunks with y-argument 100 | * [2016-06-19] [BeYkeRYkt] Upload first 3.0.0-dev code 101 | * [2016-06-16] [BeYkeRYkt] Merge pull request #2 from Androkai/master 102 | |\ 103 | | * [2016-06-15] [Christoph Krüger] Update for Minecraft 1.10 104 | | * [2016-06-15] [Christoph Krüger] Update for Minecraft 1.10 105 | | * [2016-06-15] [Christoph Krüger] Update to version 2.0.3 for Minecraft 1.10 106 | |/ 107 | * [2016-05-18] [BeYkeRYkt] Just update to 1.9.4 108 | * [2016-04-03] [BeYkeRYkt] Release 2.0.1 109 | * [2016-04-03] [BeYkeRYkt] Upload new logo 110 | * [2016-03-20] [BeYkeRYkt] Reupload (for fix incorrect name folders by GitHub client) 111 | * [2016-03-20] [BeYkeRYkt] Delete source code 112 | * [2016-03-19] [BeYkeRYkt] Update 2.0.0-Experimental 113 | * [2015-08-25] [BeYkeRYkt] Update 1.4.2 114 | * [2015-08-21] [BeYkeRYkt] Update 1.4.1 115 | * [2015-06-03] [BeYkeRYkt] Fix Cauldron imports 116 | * [2015-06-03] [BeYkeRYkt] Update 1.3.1 117 | * [2015-05-18] [BeYkeRYkt] Update 1.2.1 118 | * [2015-05-17] [BeYkeRYkt] Update 1.2.0 119 | * [2015-03-15] [BeYkeRYkt] Update 1.1 120 | * [2015-03-01] [BeYkeRYkt] Delete .classpath 121 | * [2015-03-01] [BeYkeRYkt] Init 1.0 122 | * [2015-02-28] [BeYkeRYkt] Initial commit -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ================ 2 | LightAPI Licence 3 | ================ 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2016-2017 The ImplexDevOne Project 8 | Copyright (c) 2019 Vladimir Mikhailov 9 | Copyright (c) 2021 LOOHP 10 | Copyright (c) 2021 Qveshn 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | 30 | ========================= 31 | Metrics Licence (mcstats) 32 | ========================= 33 | 34 | Copyright 2011-2013 Tyler Blair. All rights reserved. 35 | 36 | Redistribution and use in source and binary forms, with or without modification, are 37 | permitted provided that the following conditions are met: 38 | 39 | 1. Redistributions of source code must retain the above copyright notice, this list of 40 | conditions and the following disclaimer. 41 | 42 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 43 | of conditions and the following disclaimer in the documentation and/or other materials 44 | provided with the distribution. 45 | 46 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED 47 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 48 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 49 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 52 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 53 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 54 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 | 56 | The views and conclusions contained in the software and documentation are those of the 57 | authors and contributors and should not be interpreted as representing official policies, 58 | either expressed or implied, of anybody else. 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Image](/others/light_api_logo_version_3.png) 2 | # LightAPI (Fork) 3 | Library for creating invisible light source. 4 | Bukkit plugin for Minecraft server 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17. 5 | 6 | - [ SPIGOT RESOURCE ](https://www.spigotmc.org/resources/lightapi-temporary-fork.48247/) ([ original ](https://www.spigotmc.org/resources/lightapi.4510/)) 7 | - [ CONTRIBUTORS ](https://github.com/Qveshn/LightAPI/graphs/contributors) ([ original ](https://github.com/BeYkeRYkt/LightAPI/graphs/contributors)) 8 | 9 | # License 10 | > The MIT License (MIT) 11 | > 12 | > Copyright (c) 2016-2017 The ImplexDevOne Project 13 | > Copyright (c) 2019 Vladimir Mikhailov <beykerykt@gmail.com> 14 | > Copyright (c) 2021 LOOHP <jamesloohp@gmail.com> 15 | > Copyright (c) 2021 Qveshn 16 | > 17 | >Permission is hereby granted, free of charge, to any person obtaining a copy 18 | >of this software and associated documentation files (the "Software"), to deal 19 | >in the Software without restriction, including without limitation the rights 20 | >to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 21 | >copies of the Software, and to permit persons to whom the Software is 22 | >furnished to do so, subject to the following conditions: 23 | > 24 | >The above copyright notice and this permission notice shall be included in all 25 | >copies or substantial portions of the Software. 26 | > 27 | >THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | >IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | >FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | >AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | >LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | >OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | >SOFTWARE. 34 | 35 | ## Metrics Licence (mcstats) 36 | Copyright 2011-2013 Tyler Blair. All rights reserved. 37 | 38 | Redistribution and use in source and binary forms, with or without modification, are 39 | permitted provided that the following conditions are met: 40 | 41 | 1. Redistributions of source code must retain the above copyright notice, this list of 42 | conditions and the following disclaimer. 43 | 44 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 45 | of conditions and the following disclaimer in the documentation and/or other materials 46 | provided with the distribution. 47 | 48 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED 49 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 50 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 51 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 53 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 54 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 55 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 56 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | 58 | The views and conclusions contained in the software and documentation are those of the 59 | authors and contributors and should not be interpreted as representing official policies, 60 | either expressed or implied, of anybody else. 61 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi 8 | common 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | spigot-repo 21 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 22 | 23 | 24 | 25 | 26 | 27 | org.spigotmc 28 | spigot-api 29 | 1.17.1-R0.1-SNAPSHOT 30 | 31 | 32 | -------------------------------------------------------------------------------- /common/src/main/java/ru/beykerykt/lightapi/LightType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * Copyright (c) 2016-2017 The ImplexDevOne Project 6 | * Copyright (c) 2019 Qveshn 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | package ru.beykerykt.lightapi; 27 | 28 | public enum LightType { 29 | SKY, 30 | BLOCK 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/ru/beykerykt/lightapi/chunks/ChunkInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * Copyright (c) 2019 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.chunks; 26 | 27 | import org.bukkit.World; 28 | import org.bukkit.entity.Player; 29 | 30 | import java.util.Collection; 31 | 32 | public class ChunkInfo { 33 | 34 | private World world; 35 | private int x; 36 | private int y; 37 | private int z; 38 | private Collection receivers; 39 | 40 | @Deprecated 41 | public ChunkInfo(World world, int chunkX, int chunkZ, Collection players) { 42 | this(world, chunkX, 256, chunkZ, players); 43 | } 44 | 45 | public ChunkInfo(World world, int chunkX, int chunk_y_height, int chunkZ, Collection players) { 46 | this.world = world; 47 | this.x = chunkX; 48 | this.y = chunk_y_height >> 4; 49 | this.z = chunkZ; 50 | this.receivers = players; 51 | } 52 | 53 | public World getWorld() { 54 | return world; 55 | } 56 | 57 | public int getChunkX() { 58 | return x; 59 | } 60 | 61 | public int getChunkY() { 62 | return y; 63 | } 64 | 65 | public int getChunkZ() { 66 | return z; 67 | } 68 | 69 | @Deprecated 70 | public int getChunkYHeight() { 71 | return y << 4; 72 | } 73 | 74 | @Deprecated 75 | public void setChunkYHeight(int y) { 76 | this.y = y; 77 | } 78 | 79 | public Collection getReceivers() { 80 | return receivers; 81 | } 82 | 83 | public void setReceivers(Collection receivers) { 84 | this.receivers = receivers; 85 | } 86 | 87 | @Override 88 | public int hashCode() { 89 | final int prime = 31; 90 | int result = 1; 91 | result = prime * result + ((world == null) ? 0 : world.hashCode()); 92 | result = prime * result + x; 93 | result = prime * result + z; 94 | result = prime * result + y; 95 | return result; 96 | } 97 | 98 | @Override 99 | public boolean equals(Object obj) { 100 | if (this == obj) { 101 | return true; 102 | } 103 | if (obj == null) { 104 | return false; 105 | } 106 | if (!(obj instanceof ChunkInfo)) { 107 | return false; 108 | } 109 | ChunkInfo other = (ChunkInfo) obj; 110 | if (world == null) { 111 | if (other.world != null) { 112 | return false; 113 | } 114 | } else if (!world.getName().equals(other.world.getName())) { 115 | return false; 116 | } 117 | return x == other.x && z == other.z && y == other.y; 118 | } 119 | 120 | @Override 121 | public String toString() { 122 | return "ChunkInfo [world=" + world + ", x=" + x + ", y=" + y + ", z=" + z + "]"; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /common/src/main/java/ru/beykerykt/lightapi/server/nms/INMSHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * Copyright (c) 2021 LOOHP 6 | * Copyright (c) 2021 Qveshn 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | package ru.beykerykt.lightapi.server.nms; 27 | 28 | import java.util.BitSet; 29 | import java.util.Collection; 30 | import java.util.List; 31 | 32 | import org.bukkit.World; 33 | import org.bukkit.entity.Player; 34 | 35 | import ru.beykerykt.lightapi.LightType; 36 | import ru.beykerykt.lightapi.chunks.ChunkInfo; 37 | 38 | public interface INMSHandler { 39 | 40 | // Lights... 41 | @Deprecated 42 | void createLight(World world, int x, int y, int z, int light); 43 | 44 | void createLight(World world, int x, int y, int z, LightType lightType, int light); 45 | 46 | @Deprecated 47 | void deleteLight(World world, int x, int y, int z); 48 | 49 | void deleteLight(World world, int x, int y, int z, LightType lightType); 50 | 51 | @Deprecated 52 | void recalculateLight(World world, int x, int y, int z); 53 | 54 | // Chunks... 55 | @Deprecated 56 | List collectChunks(World world, int x, int y, int z); 57 | 58 | @Deprecated 59 | List collectChunks(World world, int blockX, int blockY, int blockZ, int lightLevel); 60 | 61 | List collectChunks(World world, int blockX, int blockY, int blockZ, LightType lightType, int lightLevel); 62 | 63 | @Deprecated 64 | void sendChunkSectionsUpdate( 65 | World world, int chunkX, int chunkZ, int sectionsMask, Collection players 66 | ); 67 | 68 | @Deprecated 69 | void sendChunkSectionsUpdate(World world, int chunkX, int chunkZ, int sectionsMask, Player player); 70 | 71 | @Deprecated 72 | void sendChunkUpdate(World world, int chunkX, int chunkZ, Collection players); 73 | 74 | @Deprecated 75 | void sendChunkUpdate(World world, int chunkX, int chunkZ, Player player); 76 | 77 | @Deprecated 78 | void sendChunkUpdate(World world, int chunkX, int y, int chunkZ, Collection players); 79 | 80 | @Deprecated 81 | void sendChunkUpdate(World world, int chunkX, int y, int chunkZ, Player player); 82 | 83 | @Deprecated 84 | void sendChunkSectionsUpdate( 85 | World world, 86 | int chunkX, 87 | int chunkZ, 88 | int sectionsMaskSky, 89 | int sectionsMaskBlock, 90 | Collection players 91 | ); 92 | 93 | @Deprecated 94 | void sendChunkSectionsUpdate( 95 | World world, 96 | int chunkX, 97 | int chunkZ, 98 | int sectionsMaskSky, 99 | int sectionsMaskBlock, 100 | Player player 101 | ); 102 | 103 | void sendChunkSectionsUpdate( 104 | World world, 105 | int chunkX, 106 | int chunkZ, 107 | BitSet sectionsMaskSky, 108 | BitSet sectionsMaskBlock, 109 | Collection players 110 | ); 111 | 112 | void sendChunkSectionsUpdate( 113 | World world, 114 | int chunkX, 115 | int chunkZ, 116 | BitSet sectionsMaskSky, 117 | BitSet sectionsMaskBlock, 118 | Player player 119 | ); 120 | 121 | // Utils... 122 | boolean isValidSectionY(World world, int sectionY); 123 | 124 | @Deprecated 125 | int asSectionMask(int sectionY); 126 | 127 | BitSet asSectionMask(World world, int sectionY); 128 | 129 | Collection filterVisiblePlayers( 130 | World world, int chunkX, int chunkZ, Collection players 131 | ); 132 | 133 | boolean isSupported(World world, LightType lightType); 134 | 135 | int getMinLightHeight(World world); 136 | 137 | int getMaxLightHeight(World world); 138 | } 139 | -------------------------------------------------------------------------------- /common/src/main/java/ru/beykerykt/lightapi/server/nms/NmsHandlerBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 LOOHP 5 | * Copyright (c) 2021 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.server.nms; 26 | 27 | import org.bukkit.Bukkit; 28 | import org.bukkit.Location; 29 | import org.bukkit.World; 30 | import org.bukkit.entity.Player; 31 | import ru.beykerykt.lightapi.LightType; 32 | import ru.beykerykt.lightapi.chunks.ChunkInfo; 33 | 34 | import java.util.ArrayList; 35 | import java.util.BitSet; 36 | import java.util.Collection; 37 | import java.util.List; 38 | 39 | public abstract class NmsHandlerBase implements INMSHandler { 40 | 41 | @Override 42 | public int getMinLightHeight(World world) { 43 | // Always 0 for 1.8 - 1.13.2 (v1_8_R1 - v1_13_R2) (same as world min height) 44 | // Should be overridden for other versions 45 | return 0; 46 | } 47 | 48 | @Override 49 | public int getMaxLightHeight(World world) { 50 | // Always 256 for 1.8 - 1.13.2 (v1_8_R1 - v1_13_R2) (same as world max height) 51 | // Should be overridden for other versions 52 | return world.getMaxHeight(); 53 | } 54 | 55 | private int getMinLightSection(World world) { 56 | return getMinLightHeight(world) >> 4; 57 | } 58 | 59 | private int getMaxLightSection(World world) { 60 | return (getMaxLightHeight(world) + 15) >> 4; 61 | } 62 | 63 | @Override 64 | public final boolean isValidSectionY(World world, int sectionY) { 65 | return sectionY >= getMinLightSection(world) && sectionY < getMaxLightSection(world); 66 | } 67 | 68 | @Override 69 | public int asSectionMask(int sectionY) { 70 | return 1 << sectionY; 71 | } 72 | 73 | @Override 74 | public BitSet asSectionMask(World world, int sectionY) { 75 | return BitSet.valueOf(new long[]{asSectionMask(sectionY)}); 76 | } 77 | 78 | protected int getViewDistance(Player player) { 79 | return Bukkit.getViewDistance(); 80 | } 81 | 82 | private boolean isVisibleToPlayer(World world, int chunkX, int chunkZ, Player player) { 83 | Location location = player.getLocation(); 84 | if (!world.equals(location.getWorld())) return false; 85 | int viewDistance = getViewDistance(player); 86 | int dx = chunkX - (location.getBlockX() >> 4); 87 | if (dx > viewDistance || -dx > viewDistance) return false; 88 | int dz = chunkZ - (location.getBlockZ() >> 4); 89 | return dz <= viewDistance && -dz <= viewDistance; 90 | } 91 | 92 | @Override 93 | public Collection filterVisiblePlayers( 94 | World world, int chunkX, int chunkZ, Collection players 95 | ) { 96 | List result = new ArrayList(); 97 | for (Player player : players) { 98 | if (isVisibleToPlayer(world, chunkX, chunkZ, player)) { 99 | result.add(player); 100 | } 101 | } 102 | return result; 103 | } 104 | 105 | @Deprecated 106 | @Override 107 | public void createLight(World world, int x, int y, int z, int light) { 108 | createLight(world, x, y, z, LightType.BLOCK, light); 109 | } 110 | 111 | @Deprecated 112 | @Override 113 | public void deleteLight(World world, int x, int y, int z) { 114 | deleteLight(world, x, y, z, LightType.BLOCK); 115 | } 116 | 117 | @Override 118 | public List collectChunks(World world, int blockX, int blockY, int blockZ, int lightLevel 119 | ) { 120 | return collectChunks(world, blockX, blockY, blockZ, LightType.BLOCK, lightLevel); 121 | } 122 | 123 | @Override 124 | public List collectChunks( 125 | World world, int blockX, int blockY, int blockZ, LightType lightType, int lightLevel 126 | ) { 127 | List list = new ArrayList(); 128 | Collection players = null; 129 | if (lightLevel > 0) { 130 | for (int dx = -1; dx <= 1; dx++) { 131 | int lightLevelX = lightLevel - getDeltaLight(blockX & 15, dx); 132 | if (lightLevelX > 0) { 133 | for (int dz = -1; dz <= 1; dz++) { 134 | int lightLevelZ = lightLevelX - getDeltaLight(blockZ & 15, dz); 135 | if (lightLevelZ > 0) { 136 | for (int dy = -1; dy <= 1; dy++) { 137 | if (lightLevelZ > getDeltaLight(blockY & 15, dy)) { 138 | int sectionY = (blockY >> 4) + dy; 139 | if (isValidSectionY(world, sectionY)) { 140 | int chunkX = blockX >> 4; 141 | int chunkZ = blockZ >> 4; 142 | ChunkInfo cCoord = new ChunkInfo( 143 | world, 144 | chunkX + dx, 145 | sectionY << 4, 146 | chunkZ + dz, 147 | players != null ? players : (players = world.getPlayers())); 148 | list.add(cCoord); 149 | } 150 | } 151 | } 152 | } 153 | } 154 | } 155 | } 156 | } 157 | return list; 158 | } 159 | 160 | private int getDeltaLight(int x, int dx) { 161 | return (((x ^ ((-dx >> 4) & 15)) + 1) & (-(dx & 1))); 162 | } 163 | 164 | @Deprecated 165 | @Override 166 | public void sendChunkSectionsUpdate( 167 | World world, int chunkX, int chunkZ, int sectionsMask, Collection players 168 | ) { 169 | sendChunkSectionsUpdate(world, chunkX, chunkZ, 0, sectionsMask, players); 170 | } 171 | 172 | @Override 173 | public void sendChunkSectionsUpdate( 174 | World world, int chunkX, int chunkZ, 175 | int sectionsMaskSky, int sectionsMaskBlock, Collection players 176 | ) { 177 | for (Player player : players) { 178 | sendChunkSectionsUpdate(world, chunkX, chunkZ, sectionsMaskSky, sectionsMaskBlock, player); 179 | } 180 | } 181 | 182 | @Override 183 | public void sendChunkSectionsUpdate( 184 | World world, int chunkX, int chunkZ, 185 | BitSet sectionsMaskSky, BitSet sectionsMaskBlock, Collection players 186 | ) { 187 | for (Player player : players) { 188 | sendChunkSectionsUpdate(world, chunkX, chunkZ, sectionsMaskSky, sectionsMaskBlock, player); 189 | } 190 | } 191 | 192 | private int toInt(BitSet mask) { 193 | return mask.isEmpty() ? 0 : (int) mask.toLongArray()[0]; 194 | } 195 | 196 | @Override 197 | public void sendChunkSectionsUpdate( 198 | World world, int chunkX, int chunkZ, 199 | BitSet sectionsMaskSky, BitSet sectionsMaskBlock, Player player 200 | ) { 201 | sendChunkSectionsUpdate(world, chunkX, chunkZ, toInt(sectionsMaskSky), toInt(sectionsMaskBlock), player); 202 | } 203 | 204 | @Deprecated 205 | @Override 206 | public void sendChunkSectionsUpdate(World world, int chunkX, int chunkZ, int sectionsMask, Player player) { 207 | sendChunkSectionsUpdate(world, chunkX, chunkZ, 0, sectionsMask, player); 208 | } 209 | 210 | @Deprecated 211 | @Override 212 | public void recalculateLight(World world, int x, int y, int z) { 213 | recalculateLighting(world, x, y, z, LightType.BLOCK); 214 | } 215 | 216 | protected abstract void recalculateLighting(World world, int x, int y, int z, LightType lightType); 217 | 218 | protected void recalculateNeighbours(World world, int x, int y, int z, LightType lightType) { 219 | recalculateLighting(world, x - 1, y, z, lightType); 220 | recalculateLighting(world, x + 1, y, z, lightType); 221 | recalculateLighting(world, x, y - 1, z, lightType); 222 | recalculateLighting(world, x, y + 1, z, lightType); 223 | recalculateLighting(world, x, y, z - 1, lightType); 224 | recalculateLighting(world, x, y, z + 1, lightType); 225 | } 226 | 227 | @Deprecated 228 | @Override 229 | public List collectChunks(World world, int x, int y, int z) { 230 | return collectChunks(world, x, y, z, LightType.BLOCK, 15); 231 | } 232 | 233 | @Deprecated 234 | @Override 235 | public void sendChunkUpdate(World world, int chunkX, int chunkZ, Collection players) { 236 | sendChunkSectionsUpdate(world, chunkX, chunkZ, 0, isValidSectionY(world, -1) ? 0x3ffff : 0xffff, players); 237 | } 238 | 239 | @Deprecated 240 | @Override 241 | public void sendChunkUpdate(World world, int chunkX, int chunkZ, Player player) { 242 | sendChunkSectionsUpdate(world, chunkX, chunkZ, 0, isValidSectionY(world, -1) ? 0x3ffff : 0xffff, player); 243 | } 244 | 245 | @Deprecated 246 | @Override 247 | public void sendChunkUpdate(World world, int chunkX, int y, int chunkZ, Collection players) { 248 | int mask = getThreeSectionsMask(world, y); 249 | if (mask != 0) sendChunkSectionsUpdate(world, chunkX, chunkZ, 0, mask, players); 250 | } 251 | 252 | @Deprecated 253 | @Override 254 | public void sendChunkUpdate(World world, int chunkX, int y, int chunkZ, Player player) { 255 | int mask = getThreeSectionsMask(world, y); 256 | if (mask != 0) sendChunkSectionsUpdate(world, chunkX, chunkZ, 0, mask, player); 257 | } 258 | 259 | private int getThreeSectionsMask(World world, int y) { 260 | return (isValidSectionY(world, y) ? asSectionMask(y) : 0) 261 | | (isValidSectionY(world, y - 1) ? asSectionMask(y - 1) : 0) 262 | | (isValidSectionY(world, y + 1) ? asSectionMask(y + 1) : 0); 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /common/src/main/java/ru/beykerykt/lightapi/utils/Debug.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Qveshn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.utils; 25 | 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.ChatColor; 28 | 29 | import java.util.HashMap; 30 | import java.util.Map; 31 | import java.util.logging.Level; 32 | 33 | /** 34 | * Light static debug mechanics to print messages 35 | * Using: 36 | *

37 | * 1. Init prefix and its foreground and background colors. 38 | * Example: Debug.setPrefix(plugin.getName(), ChatColor.WHITE, ChatColor.DARK_BLUE); 39 | *

40 | * 2. Enable output 41 | * Example: Debug.setEnable(true); 42 | *

43 | * 3. Print a message anywhere in the code 44 | * Example: Debug.print("Hello %s!", "World"); 45 | */ 46 | public class Debug { 47 | 48 | private static boolean isEnabled = false; 49 | private static String coloredPrefix = ""; 50 | 51 | private static String getColorPrefix(String prefix, ChatColor fg, ChatColor bg) { 52 | if (prefix == null || prefix.isEmpty()) { 53 | return ""; 54 | } 55 | StringBuilder sb = new StringBuilder(); 56 | ChatColorToAnsi c; 57 | if (fg != null && (c = ChatColorToAnsi.valueOf(fg)) != null) { 58 | sb.append(';').append(c.fg()); 59 | } 60 | if (bg != null && (c = ChatColorToAnsi.valueOf(bg)) != null) { 61 | sb.append(';').append(c.bg()); 62 | } 63 | return sb.length() > 0 64 | ? String.format("\u001b[%sm[%s]\u001b[m ", sb.substring(1), prefix) 65 | : String.format("[!!!%s] ", prefix); 66 | } 67 | 68 | /** 69 | * Set prefix which will be printed in squared brackets before message 70 | * 71 | * @param prefix The prefix (usually the plugin name) 72 | * @param fg The foreground color of the prefix. 73 | * @param bg The background color of the prefix. 74 | */ 75 | public static void setPrefix(String prefix, ChatColor fg, ChatColor bg) { 76 | coloredPrefix = getColorPrefix(prefix, fg, bg); 77 | } 78 | 79 | /** 80 | * Enable or disable print command 81 | * 82 | * @param enabled Enables print command if true. Otherwise, disables print command 83 | */ 84 | public static void setEnable(boolean enabled) { 85 | Debug.isEnabled = enabled; 86 | } 87 | 88 | /** 89 | * Checks if debug print command is enabled. 90 | * 91 | * @return The true value if debug print command is enabled. Otherwise, returns false. 92 | */ 93 | public static boolean isEnabled() { 94 | return isEnabled; 95 | } 96 | 97 | /** 98 | * Prints a formatted string using the specified format string and arguments like 99 | * {@link String#format(String, Object...) String.format} does. 100 | * 101 | * @param format A format string if arguments exist or a simple text if no arguments exist. 102 | * @param args Arguments referenced by the format string. 103 | */ 104 | public static void print(String format, Object... args) { 105 | if (isEnabled) { 106 | Bukkit.getLogger().log( 107 | Level.INFO, 108 | String.format("%s%s", 109 | coloredPrefix, 110 | args == null || args.length == 0 111 | ? format 112 | : String.format(format, args) 113 | )); 114 | } 115 | } 116 | 117 | private enum AnsiColor { 118 | BLACK(0), 119 | RED(1), 120 | GREEN(2), 121 | YELLOW(3), 122 | BLUE(4), 123 | MAGENTA(5), 124 | CYAN(6), 125 | WHITE(7); 126 | 127 | private final int value; 128 | 129 | AnsiColor(int index) { 130 | this.value = index; 131 | } 132 | 133 | public int fg() { 134 | return value + 30; 135 | } 136 | 137 | public int bg() { 138 | return value + 40; 139 | } 140 | } 141 | 142 | @SuppressWarnings("unused") 143 | private enum ChatColorToAnsi { 144 | BLACK(ChatColor.BLACK, AnsiColor.BLACK, false), 145 | DARK_BLUE(ChatColor.DARK_BLUE, AnsiColor.BLUE, false), 146 | DARK_GREEN(ChatColor.DARK_GREEN, AnsiColor.GREEN, false), 147 | DARK_AQUA(ChatColor.DARK_AQUA, AnsiColor.CYAN, false), 148 | DARK_RED(ChatColor.DARK_RED, AnsiColor.RED, false), 149 | DARK_PURPLE(ChatColor.DARK_PURPLE, AnsiColor.MAGENTA, false), 150 | GOLD(ChatColor.GOLD, AnsiColor.YELLOW, false), 151 | GRAY(ChatColor.GRAY, AnsiColor.WHITE, false), 152 | DARK_GRAY(ChatColor.DARK_GRAY, AnsiColor.BLACK, true), 153 | BLUE(ChatColor.BLUE, AnsiColor.BLUE, true), 154 | GREEN(ChatColor.GREEN, AnsiColor.GREEN, true), 155 | AQUA(ChatColor.AQUA, AnsiColor.CYAN, true), 156 | RED(ChatColor.RED, AnsiColor.RED, true), 157 | LIGHT_PURPLE(ChatColor.LIGHT_PURPLE, AnsiColor.MAGENTA, true), 158 | YELLOW(ChatColor.YELLOW, AnsiColor.YELLOW, true), 159 | WHITE(ChatColor.WHITE, AnsiColor.WHITE, true); 160 | 161 | private final ChatColor chatColor; 162 | private final AnsiColor ansiColor; 163 | private final boolean bright; 164 | 165 | ChatColorToAnsi(ChatColor chatColor, AnsiColor ansiColor, boolean bright) { 166 | this.chatColor = chatColor; 167 | this.ansiColor = ansiColor; 168 | this.bright = bright; 169 | } 170 | 171 | public String fg() { 172 | return String.format(bright ? "%d;1" : "%d", ansiColor.fg()); 173 | } 174 | 175 | public String bg() { 176 | return String.format(bright ? "%d;1" : "%d", ansiColor.bg()); 177 | } 178 | 179 | private static Map mapFromChatColor = new HashMap(); 180 | 181 | static { 182 | for (ChatColorToAnsi value : ChatColorToAnsi.values()) { 183 | mapFromChatColor.put(value.chatColor, value); 184 | } 185 | } 186 | 187 | public static ChatColorToAnsi valueOf(ChatColor chatColor) { 188 | return mapFromChatColor.get(chatColor); 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /common/src/main/java/ru/beykerykt/lightapi/utils/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Qveshn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.utils; 25 | 26 | import org.bukkit.Bukkit; 27 | 28 | import java.util.regex.Matcher; 29 | import java.util.regex.Pattern; 30 | 31 | public class Utils { 32 | 33 | public static String serverVersion() { 34 | return Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; 35 | } 36 | 37 | public static String serverName() { 38 | return Bukkit.getVersion().split("-")[1]; 39 | } 40 | 41 | public static String bukkitName() { 42 | return Bukkit.getName(); 43 | } 44 | 45 | public static String bukkitVersion() { 46 | return (Bukkit.getBukkitVersion() + "-").split("-")[0]; 47 | } 48 | 49 | private static String paddedVersion(String value) { 50 | return Utils.leftPad(value, "\\d+", '0', 8); 51 | } 52 | 53 | private static String paddedBukkitVersion() { 54 | return paddedVersion(bukkitVersion()); 55 | } 56 | 57 | public static int compareBukkitVersionTo(String version) { 58 | return paddedBukkitVersion().compareTo(paddedVersion(version)); 59 | } 60 | 61 | private static String leftPad(String text, String regex, char padCharacter, int width) { 62 | StringBuilder sb = new StringBuilder(); 63 | Matcher m = Pattern.compile(regex).matcher(text); 64 | String chars = String.format("%" + width + "s", "").replace(' ', padCharacter); 65 | int last = 0; 66 | while (m.find()) { 67 | int start = m.start(); 68 | int n = m.end() - start; 69 | if (n < width) { 70 | sb.append(text, last, start); 71 | sb.append(chars, n, width); 72 | last = start; 73 | } 74 | } 75 | if (last == 0) return text; 76 | if (last < text.length()) sb.append(text, last, text.length()); 77 | return sb.toString(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /nms/v1_10_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_10_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.10.2-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_10_R1/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_10_R1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Vladimir Mikhailov 5 | * Copyright (c) 2020 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 26 | 27 | import net.minecraft.server.v1_10_R1.*; 28 | import org.bukkit.World; 29 | import org.bukkit.craftbukkit.v1_10_R1.CraftWorld; 30 | import org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer; 31 | import org.bukkit.entity.Player; 32 | import ru.beykerykt.lightapi.LightType; 33 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 34 | 35 | public class CraftBukkit_v1_10_R1 extends NmsHandlerBase { 36 | 37 | @Override 38 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 39 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 40 | worldServer.a(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, 41 | new BlockPosition(x, y, z), light); 42 | recalculateNeighbours(world, x, y, z, lightType); 43 | } 44 | 45 | @Override 46 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 47 | recalculateLighting(world, x, y, z, lightType); 48 | } 49 | 50 | @Override 51 | protected void recalculateLighting(World world, int x, int y, int z, LightType lightType) { 52 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 53 | BlockPosition position = new BlockPosition(x, y, z); 54 | worldServer.c(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, position); 55 | } 56 | 57 | @Override 58 | public void sendChunkSectionsUpdate( 59 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 60 | ) { 61 | int sectionsMask = sectionsMaskSky | sectionsMaskBlock; 62 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 63 | // The last argument is bit-mask what chunk sections to update. Mask containing 64 | // 16 bits, with the lowest bit corresponding to chunk section 0 (y=0 to y=15) 65 | // and the highest bit for chunk section 15 (y=240 to 255). 66 | PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(chunk, sectionsMask); 67 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 68 | } 69 | 70 | @Override 71 | public boolean isSupported(World world, LightType lightType) { 72 | if (!(world instanceof CraftWorld)) { 73 | return false; 74 | } 75 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 76 | if (lightType == LightType.SKY) { 77 | return !worldServer.worldProvider.m(); 78 | } else { 79 | return true; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /nms/v1_11_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_11_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.11-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_11_R1/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_11_R1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Vladimir Mikhailov 5 | * Copyright (c) 2020 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 26 | 27 | import net.minecraft.server.v1_11_R1.*; 28 | import org.bukkit.World; 29 | import org.bukkit.craftbukkit.v1_11_R1.CraftWorld; 30 | import org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer; 31 | import org.bukkit.entity.Player; 32 | import ru.beykerykt.lightapi.LightType; 33 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 34 | 35 | public class CraftBukkit_v1_11_R1 extends NmsHandlerBase { 36 | 37 | @Override 38 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 39 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 40 | worldServer.a(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, 41 | new BlockPosition(x, y, z), light); 42 | recalculateNeighbours(world, x, y, z, lightType); 43 | } 44 | 45 | @Override 46 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 47 | recalculateLighting(world, x, y, z, lightType); 48 | } 49 | 50 | @Override 51 | protected void recalculateLighting(World world, int x, int y, int z, LightType lightType) { 52 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 53 | BlockPosition position = new BlockPosition(x, y, z); 54 | worldServer.c(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, position); 55 | } 56 | 57 | @Override 58 | public void sendChunkSectionsUpdate( 59 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 60 | ) { 61 | int sectionsMask = sectionsMaskSky | sectionsMaskBlock; 62 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 63 | // The last argument is bit-mask what chunk sections to update. Mask containing 64 | // 16 bits, with the lowest bit corresponding to chunk section 0 (y=0 to y=15) 65 | // and the highest bit for chunk section 15 (y=240 to 255). 66 | PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(chunk, sectionsMask); 67 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 68 | } 69 | 70 | @Override 71 | public boolean isSupported(World world, LightType lightType) { 72 | if (!(world instanceof CraftWorld)) { 73 | return false; 74 | } 75 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 76 | if (lightType == LightType.SKY) { 77 | return worldServer.worldProvider.m(); 78 | } else { 79 | return true; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /nms/v1_12_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_12_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.12.2-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_12_R1/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_12_R1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Vladimir Mikhailov 5 | * Copyright (c) 2020 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 26 | 27 | import net.minecraft.server.v1_12_R1.*; 28 | import org.bukkit.World; 29 | import org.bukkit.craftbukkit.v1_12_R1.CraftWorld; 30 | import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; 31 | import org.bukkit.entity.Player; 32 | import ru.beykerykt.lightapi.LightType; 33 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 34 | 35 | public class CraftBukkit_v1_12_R1 extends NmsHandlerBase { 36 | 37 | @Override 38 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 39 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 40 | worldServer.a(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, 41 | new BlockPosition(x, y, z), light); 42 | recalculateNeighbours(world, x, y, z, lightType); 43 | } 44 | 45 | @Override 46 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 47 | recalculateLighting(world, x, y, z, lightType); 48 | } 49 | 50 | @Override 51 | protected void recalculateLighting(World world, int x, int y, int z, LightType lightType) { 52 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 53 | BlockPosition position = new BlockPosition(x, y, z); 54 | worldServer.c(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, position); 55 | } 56 | 57 | @Override 58 | public void sendChunkSectionsUpdate( 59 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 60 | ) { 61 | int sectionsMask = sectionsMaskSky | sectionsMaskBlock; 62 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 63 | // The last argument is bit-mask what chunk sections to update. Mask containing 64 | // 16 bits, with the lowest bit corresponding to chunk section 0 (y=0 to y=15) 65 | // and the highest bit for chunk section 15 (y=240 to 255). 66 | PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(chunk, sectionsMask); 67 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 68 | } 69 | 70 | @Override 71 | public boolean isSupported(World world, LightType lightType) { 72 | if (!(world instanceof CraftWorld)) { 73 | return false; 74 | } 75 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 76 | if (lightType == LightType.SKY) { 77 | return worldServer.worldProvider.m(); 78 | } else { 79 | return true; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /nms/v1_13_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_13_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.13-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_13_R1/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_13_R1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2020 Qveshn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 25 | 26 | import net.minecraft.server.v1_13_R1.*; 27 | import org.bukkit.World; 28 | import org.bukkit.craftbukkit.v1_13_R1.CraftWorld; 29 | import org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer; 30 | import org.bukkit.entity.Player; 31 | import ru.beykerykt.lightapi.LightType; 32 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 33 | 34 | public class CraftBukkit_v1_13_R1 extends NmsHandlerBase { 35 | 36 | @Override 37 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 38 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 39 | worldServer.a(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, 40 | new BlockPosition(x, y, z), light); 41 | recalculateNeighbours(world, x, y, z, lightType); 42 | } 43 | 44 | @Override 45 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 46 | recalculateLighting(world, x, y, z, lightType); 47 | } 48 | 49 | @Override 50 | protected void recalculateLighting(World world, int x, int y, int z, LightType lightType) { 51 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 52 | BlockPosition position = new BlockPosition(x, y, z); 53 | worldServer.c(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, position); 54 | } 55 | 56 | @Override 57 | public void sendChunkSectionsUpdate( 58 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 59 | ) { 60 | int sectionsMask = sectionsMaskSky | sectionsMaskBlock; 61 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 62 | // The last argument is bit-mask what chunk sections to update. Mask containing 63 | // 16 bits, with the lowest bit corresponding to chunk section 0 (y=0 to y=15) 64 | // and the highest bit for chunk section 15 (y=240 to 255). 65 | PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(chunk, sectionsMask); 66 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 67 | } 68 | 69 | @Override 70 | public boolean isSupported(World world, LightType lightType) { 71 | if (!(world instanceof CraftWorld)) { 72 | return false; 73 | } 74 | if (lightType == LightType.SKY) { 75 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 76 | return worldServer.worldProvider.g(); 77 | } else { 78 | return true; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /nms/v1_13_R2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_13_R2 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.13.2-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_13_R2/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_13_R2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2020 Qveshn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 25 | 26 | import net.minecraft.server.v1_13_R2.*; 27 | import org.bukkit.World; 28 | import org.bukkit.craftbukkit.v1_13_R2.CraftWorld; 29 | import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer; 30 | import org.bukkit.entity.Player; 31 | import ru.beykerykt.lightapi.LightType; 32 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 33 | 34 | public class CraftBukkit_v1_13_R2 extends NmsHandlerBase { 35 | 36 | @Override 37 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 38 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 39 | worldServer.a(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, 40 | new BlockPosition(x, y, z), light); 41 | recalculateNeighbours(world, x, y, z, lightType); 42 | } 43 | 44 | @Override 45 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 46 | recalculateLighting(world, x, y, z, lightType); 47 | } 48 | 49 | @Override 50 | protected void recalculateLighting(World world, int x, int y, int z, LightType lightType) { 51 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 52 | BlockPosition position = new BlockPosition(x, y, z); 53 | worldServer.c(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, position); 54 | } 55 | 56 | @Override 57 | public void sendChunkSectionsUpdate( 58 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 59 | ) { 60 | int sectionsMask = sectionsMaskSky | sectionsMaskBlock; 61 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 62 | // The last argument is bit-mask what chunk sections to update. Mask containing 63 | // 16 bits, with the lowest bit corresponding to chunk section 0 (y=0 to y=15) 64 | // and the highest bit for chunk section 15 (y=240 to 255). 65 | PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(chunk, sectionsMask); 66 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 67 | } 68 | 69 | @Override 70 | public boolean isSupported(World world, LightType lightType) { 71 | if (!(world instanceof CraftWorld)) { 72 | return false; 73 | } 74 | if (lightType == LightType.SKY) { 75 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 76 | return worldServer.worldProvider.g(); 77 | } else { 78 | return true; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /nms/v1_14_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_14_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.14.4-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_14_R1/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_14_R1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016-2017 The ImplexDevOne Project 5 | * Copyright (c) 2019 Vladimir Mikhailov 6 | * Copyright (c) 2021 Qveshn 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 27 | 28 | import net.minecraft.server.v1_14_R1.*; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_14_R1.CraftWorld; 31 | import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; 32 | import org.bukkit.entity.Player; 33 | import ru.beykerykt.lightapi.chunks.ChunkInfo; 34 | import ru.beykerykt.lightapi.LightType; 35 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 36 | import ru.beykerykt.lightapi.utils.Debug; 37 | 38 | import java.lang.reflect.Field; 39 | import java.lang.reflect.InvocationTargetException; 40 | import java.lang.reflect.Method; 41 | import java.util.ArrayList; 42 | import java.util.Collection; 43 | import java.util.List; 44 | import java.util.concurrent.atomic.AtomicInteger; 45 | 46 | public class CraftBukkit_v1_14_R1 extends NmsHandlerBase { 47 | 48 | private Field lightEngine_ThreadedMailbox; 49 | private Field threadedMailbox_State; 50 | private Method threadedMailbox_DoLoopStep; 51 | private Field lightEngineLayer_c; 52 | private Method lightEngineStorage_c; 53 | private Method lightEngineGraph_a; 54 | 55 | public CraftBukkit_v1_14_R1() { 56 | try { 57 | threadedMailbox_DoLoopStep = ThreadedMailbox.class.getDeclaredMethod("f"); 58 | threadedMailbox_DoLoopStep.setAccessible(true); 59 | threadedMailbox_State = ThreadedMailbox.class.getDeclaredField("c"); 60 | threadedMailbox_State.setAccessible(true); 61 | lightEngine_ThreadedMailbox = LightEngineThreaded.class.getDeclaredField("b"); 62 | lightEngine_ThreadedMailbox.setAccessible(true); 63 | 64 | lightEngineLayer_c = LightEngineLayer.class.getDeclaredField("c"); 65 | lightEngineLayer_c.setAccessible(true); 66 | lightEngineStorage_c = LightEngineStorage.class.getDeclaredMethod("c"); 67 | lightEngineStorage_c.setAccessible(true); 68 | lightEngineGraph_a = LightEngineGraph.class.getDeclaredMethod( 69 | "a", long.class, long.class, int.class, boolean.class); 70 | lightEngineGraph_a.setAccessible(true); 71 | } catch (Exception e) { 72 | throw toRuntimeException(e); 73 | } 74 | } 75 | 76 | @Override 77 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 78 | setRawLightLevel(world, lightType, x, y, z, light); 79 | recalculateLighting(world, x, y, z, lightType); 80 | } 81 | 82 | @Override 83 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 84 | setRawLightLevel(world, lightType, x, y, z, 0); 85 | recalculateLighting(world, x, y, z, lightType); 86 | } 87 | 88 | @SuppressWarnings("SameParameterValue") 89 | private void setRawLightLevel(World world, final LightType type, int blockX, int blockY, int blockZ, int lightlevel) { 90 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 91 | final BlockPosition position = new BlockPosition(blockX, blockY, blockZ); 92 | final LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 93 | 94 | final int finalLightLevel = lightlevel < 0 ? 0 : lightlevel > 15 ? 15 : lightlevel; 95 | executeSync(lightEngine, new Runnable() { 96 | @Override 97 | public void run() { 98 | if (type == LightType.SKY) { 99 | LightEngineLayerEventListener layer = lightEngine.a(EnumSkyBlock.SKY); 100 | if (!(layer instanceof LightEngineSky)) return; 101 | LightEngineSky les = (LightEngineSky) layer; 102 | if (finalLightLevel == 0) { 103 | les.a(position); 104 | } else if (les.a(SectionPosition.a(position)) != null) { 105 | try { 106 | lightEngineLayer_a(les, position, finalLightLevel); 107 | } catch (NullPointerException ignore) { 108 | // To prevent problems with the absence of the NibbleArray, even 109 | // if les.a(SectionPosition.a(position)) returns non-null value (corrupted data) 110 | } 111 | } 112 | } else { 113 | LightEngineLayerEventListener layer = lightEngine.a(EnumSkyBlock.BLOCK); 114 | if (!(layer instanceof LightEngineBlock)) return; 115 | LightEngineBlock leb = (LightEngineBlock) layer; 116 | if (finalLightLevel == 0) { 117 | leb.a(position); 118 | } else if (leb.a(SectionPosition.a(position)) != null) { 119 | try { 120 | leb.a(position, finalLightLevel); 121 | } catch (NullPointerException ignore) { 122 | // To prevent problems with the absence of the NibbleArray, even 123 | // if leb.a(SectionPosition.a(position)) returns non-null value (corrupted data) 124 | } 125 | } 126 | } 127 | } 128 | }); 129 | } 130 | 131 | @Override 132 | protected void recalculateLighting(World world, int blockX, int blockY, int blockZ, final LightType type) { 133 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 134 | final LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 135 | 136 | // Do not recalculate if no changes! 137 | if (!lightEngine.a()) { 138 | return; 139 | } 140 | 141 | executeSync(lightEngine, new Runnable() { 142 | @Override 143 | public void run() { 144 | if (type == LightType.SKY) { 145 | LightEngineSky les = (LightEngineSky) lightEngine.a(EnumSkyBlock.SKY); 146 | les.a(Integer.MAX_VALUE, true, true); 147 | } else { 148 | LightEngineBlock leb = (LightEngineBlock) lightEngine.a(EnumSkyBlock.BLOCK); 149 | leb.a(Integer.MAX_VALUE, true, true); 150 | } 151 | } 152 | }); 153 | } 154 | 155 | @Override 156 | public void sendChunkSectionsUpdate( 157 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 158 | ) { 159 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 160 | // https://wiki.vg/index.php?title=Pre-release_protocol&oldid=14804#Update_Light 161 | // https://github.com/flori-schwa/VarLight/blob/b9349499f9c9fb995c320f95eae9698dd85aad5c/v1_14_R1/src/me/florian/varlight/nms/v1_14_R1/NmsAdapter_1_14_R1.java#L451 162 | // 163 | // Two last argument is bit-mask what chunk sections to update. Mask containing 164 | // 18 bits, with the lowest bit corresponding to chunk section -1 (in the void, 165 | // y=-16 to y=-1) and the highest bit for chunk section 16 (above the world, 166 | // y=256 to y=271). 167 | PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate( 168 | chunk.getPos(), chunk.e(), sectionsMaskSky, sectionsMaskBlock); 169 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 170 | } 171 | 172 | @Override 173 | public int asSectionMask(int sectionY) { 174 | return 1 << sectionY + 1; 175 | } 176 | 177 | @Override 178 | protected int getViewDistance(Player player) { 179 | return player.getClientViewDistance(); 180 | } 181 | 182 | @SuppressWarnings({"StatementWithEmptyBody", "unchecked"}) 183 | private void executeSync(LightEngineThreaded lightEngine, Runnable task) { 184 | try { 185 | // ##### STEP 1: Pause light engine mailbox to process its tasks. ##### 186 | ThreadedMailbox threadedMailbox = (ThreadedMailbox) lightEngine_ThreadedMailbox 187 | .get(lightEngine); 188 | // State flags bit mask: 189 | // 0x0001 - Closing flag (ThreadedMailbox is closing if non zero). 190 | // 0x0002 - Busy flag (ThreadedMailbox performs a task from queue if non zero). 191 | AtomicInteger stateFlags = (AtomicInteger) threadedMailbox_State.get(threadedMailbox); 192 | int flags; // to hold values from stateFlags 193 | long timeToWait = -1; 194 | // Trying to set bit 1 in state bit mask when it is not set yet. 195 | // This will break the loop in other thread where light engine mailbox processes the taks. 196 | while (!stateFlags.compareAndSet(flags = stateFlags.get() & ~2, flags | 2)) { 197 | if ((flags & 1) != 0) { 198 | // ThreadedMailbox is closing. The light engine mailbox may also stop processing tasks. 199 | // The light engine mailbox can be close due to server shutdown or unloading (closing) the world. 200 | // I am not sure is it unsafe to process our tasks while the world is closing is closing, 201 | // but will try it (one can throw exception here if it crashes the server). 202 | if (timeToWait == -1) { 203 | // Try to wait 3 seconds until light engine mailbox is busy. 204 | timeToWait = System.currentTimeMillis() + 3 * 1000; 205 | Debug.print("ThreadedMailbox is closing. Will wait..."); 206 | } else if (System.currentTimeMillis() >= timeToWait) { 207 | throw new RuntimeException("Failed to enter critical section while ThreadedMailbox is closing"); 208 | } 209 | try { 210 | Thread.sleep(50); 211 | } catch (InterruptedException ignored) { 212 | } 213 | } 214 | } 215 | try { 216 | // ##### STEP 2: Safely running the task while the mailbox process is stopped. ##### 217 | task.run(); 218 | } finally { 219 | // STEP 3: ##### Continue light engine mailbox to process its tasks. ##### 220 | // Firstly: Clearing busy flag to allow ThreadedMailbox to use it for running light engine tasks. 221 | while (!stateFlags.compareAndSet(flags = stateFlags.get(), flags & ~2)) ; 222 | // Secondly: IMPORTANT! The main loop of ThreadedMailbox was broken. Not completed tasks may still be 223 | // in the queue. Therefore, it is important to start the loop again to process tasks from the queue. 224 | // Otherwise, the main server thread may be frozen due to tasks stuck in the queue. 225 | threadedMailbox_DoLoopStep.invoke(threadedMailbox); 226 | } 227 | } catch (InvocationTargetException e) { 228 | throw toRuntimeException(e.getCause()); 229 | } catch (IllegalAccessException e) { 230 | throw toRuntimeException(e); 231 | } 232 | } 233 | 234 | private void lightEngineLayer_a(LightEngineLayer les, BlockPosition var0, int var1) { 235 | try { 236 | LightEngineStorage ls = (LightEngineStorage) lightEngineLayer_c.get(les); 237 | lightEngineStorage_c.invoke(ls); 238 | lightEngineGraph_a.invoke(les, 9223372036854775807L, var0.asLong(), 15 - var1, true); 239 | } catch (InvocationTargetException e) { 240 | throw toRuntimeException(e.getCause()); 241 | } catch (IllegalAccessException e) { 242 | throw toRuntimeException(e); 243 | } 244 | } 245 | 246 | private static RuntimeException toRuntimeException(Throwable e) { 247 | if (e instanceof RuntimeException) { 248 | return (RuntimeException) e; 249 | } 250 | Class cls = e.getClass(); 251 | return new RuntimeException( 252 | String.format("(%s) %s", RuntimeException.class.getPackage().equals(cls.getPackage()) 253 | ? cls.getSimpleName() : cls.getName(), e.getMessage()), 254 | e); 255 | } 256 | 257 | private int getDeltaLight(int x, int dx) { 258 | return (((x ^ ((-dx >> 4) & 15)) + 1) & (-(dx & 1))); 259 | } 260 | 261 | @Override 262 | public List collectChunks( 263 | World world, int blockX, int blockY, int blockZ, LightType lightType, int lightLevel 264 | ) { 265 | if (lightType != LightType.SKY || lightLevel < 15) { 266 | return super.collectChunks(world, blockX, blockY, blockZ, lightType, lightLevel); 267 | } 268 | List list = new ArrayList(); 269 | Collection players = null; 270 | for (int dx = -1; dx <= 1; dx++) { 271 | int lightLevelX = lightLevel - getDeltaLight(blockX & 15, dx); 272 | if (lightLevelX > 0) { 273 | for (int dz = -1; dz <= 1; dz++) { 274 | int lightLevelZ = lightLevelX - getDeltaLight(blockZ & 15, dz); 275 | if (lightLevelZ > 0) { 276 | if (lightLevelZ > getDeltaLight(blockY & 15, 1)) { 277 | int sectionY = (blockY >> 4) + 1; 278 | if (isValidSectionY(world, sectionY)) { 279 | int chunkX = blockX >> 4; 280 | int chunkZ = blockZ >> 4; 281 | ChunkInfo cCoord = new ChunkInfo( 282 | world, 283 | chunkX + dx, 284 | sectionY << 4, 285 | chunkZ + dz, 286 | players != null ? players : (players = world.getPlayers())); 287 | list.add(cCoord); 288 | } 289 | } 290 | for (int sectionY = blockY >> 4; sectionY >= -1; sectionY--) { 291 | if (isValidSectionY(world, sectionY)) { 292 | int chunkX = blockX >> 4; 293 | int chunkZ = blockZ >> 4; 294 | ChunkInfo cCoord = new ChunkInfo( 295 | world, 296 | chunkX + dx, 297 | sectionY << 4, 298 | chunkZ + dz, 299 | players != null ? players : (players = world.getPlayers())); 300 | list.add(cCoord); 301 | } 302 | } 303 | } 304 | } 305 | } 306 | } 307 | return list; 308 | } 309 | 310 | @Override 311 | public boolean isSupported(World world, LightType lightType) { 312 | if (!(world instanceof CraftWorld)) { 313 | return false; 314 | } 315 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 316 | LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 317 | if (lightType == LightType.SKY) { 318 | return lightEngine.a(EnumSkyBlock.SKY) instanceof LightEngineSky; 319 | } else { 320 | return lightEngine.a(EnumSkyBlock.BLOCK) instanceof LightEngineBlock; 321 | } 322 | } 323 | 324 | @Override 325 | public int getMinLightHeight(World world) { 326 | return -16; 327 | } 328 | 329 | @Override 330 | public int getMaxLightHeight(World world) { 331 | return world.getMaxHeight() + 16; 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /nms/v1_15_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_15_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.15-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_15_R1/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_15_R1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016-2017 The ImplexDevOne Project 5 | * Copyright (c) 2019 Vladimir Mikhailov 6 | * Copyright (c) 2021 Qveshn 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 27 | 28 | import net.minecraft.server.v1_15_R1.*; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_15_R1.CraftWorld; 31 | import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; 32 | import org.bukkit.entity.Player; 33 | import ru.beykerykt.lightapi.chunks.ChunkInfo; 34 | import ru.beykerykt.lightapi.LightType; 35 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 36 | import ru.beykerykt.lightapi.utils.Debug; 37 | 38 | import java.lang.reflect.Field; 39 | import java.lang.reflect.InvocationTargetException; 40 | import java.lang.reflect.Method; 41 | import java.util.ArrayList; 42 | import java.util.Collection; 43 | import java.util.List; 44 | import java.util.concurrent.atomic.AtomicInteger; 45 | 46 | public class CraftBukkit_v1_15_R1 extends NmsHandlerBase { 47 | 48 | private Field lightEngine_ThreadedMailbox; 49 | private Field threadedMailbox_State; 50 | private Method threadedMailbox_DoLoopStep; 51 | private Field lightEngineLayer_c; 52 | private Method lightEngineStorage_d; 53 | private Method lightEngineGraph_a; 54 | 55 | public CraftBukkit_v1_15_R1() { 56 | try { 57 | threadedMailbox_DoLoopStep = ThreadedMailbox.class.getDeclaredMethod("f"); 58 | threadedMailbox_DoLoopStep.setAccessible(true); 59 | threadedMailbox_State = ThreadedMailbox.class.getDeclaredField("c"); 60 | threadedMailbox_State.setAccessible(true); 61 | lightEngine_ThreadedMailbox = LightEngineThreaded.class.getDeclaredField("b"); 62 | lightEngine_ThreadedMailbox.setAccessible(true); 63 | 64 | lightEngineLayer_c = LightEngineLayer.class.getDeclaredField("c"); 65 | lightEngineLayer_c.setAccessible(true); 66 | lightEngineStorage_d = LightEngineStorage.class.getDeclaredMethod("d"); 67 | lightEngineStorage_d.setAccessible(true); 68 | lightEngineGraph_a = LightEngineGraph.class.getDeclaredMethod( 69 | "a", long.class, long.class, int.class, boolean.class); 70 | lightEngineGraph_a.setAccessible(true); 71 | } catch (Exception e) { 72 | throw toRuntimeException(e); 73 | } 74 | } 75 | 76 | @Override 77 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 78 | setRawLightLevel(world, lightType, x, y, z, light); 79 | recalculateLighting(world, x, y, z, lightType); 80 | } 81 | 82 | @Override 83 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 84 | setRawLightLevel(world, lightType, x, y, z, 0); 85 | recalculateLighting(world, x, y, z, lightType); 86 | } 87 | 88 | @SuppressWarnings("SameParameterValue") 89 | private void setRawLightLevel(World world, final LightType type, int blockX, int blockY, int blockZ, int lightlevel) { 90 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 91 | final BlockPosition position = new BlockPosition(blockX, blockY, blockZ); 92 | final LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 93 | 94 | final int finalLightLevel = lightlevel < 0 ? 0 : lightlevel > 15 ? 15 : lightlevel; 95 | executeSync(lightEngine, new Runnable() { 96 | @Override 97 | public void run() { 98 | if (type == LightType.SKY) { 99 | LightEngineLayerEventListener layer = lightEngine.a(EnumSkyBlock.SKY); 100 | if (!(layer instanceof LightEngineSky)) return; 101 | LightEngineSky les = (LightEngineSky) layer; 102 | if (finalLightLevel == 0) { 103 | les.a(position); 104 | } else if (les.a(SectionPosition.a(position)) != null) { 105 | try { 106 | lightEngineLayer_a(les, position, finalLightLevel); 107 | } catch (NullPointerException ignore) { 108 | // To prevent problems with the absence of the NibbleArray, even 109 | // if les.a(SectionPosition.a(position)) returns non-null value (corrupted data) 110 | } 111 | } 112 | } else { 113 | LightEngineLayerEventListener layer = lightEngine.a(EnumSkyBlock.BLOCK); 114 | if (!(layer instanceof LightEngineBlock)) return; 115 | LightEngineBlock leb = (LightEngineBlock) layer; 116 | if (finalLightLevel == 0) { 117 | leb.a(position); 118 | } else if (leb.a(SectionPosition.a(position)) != null) { 119 | try { 120 | leb.a(position, finalLightLevel); 121 | } catch (NullPointerException ignore) { 122 | // To prevent problems with the absence of the NibbleArray, even 123 | // if leb.a(SectionPosition.a(position)) returns non-null value (corrupted data) 124 | } 125 | } 126 | } 127 | } 128 | }); 129 | } 130 | 131 | @Override 132 | protected void recalculateLighting(World world, int blockX, int blockY, int blockZ, final LightType type) { 133 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 134 | final LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 135 | 136 | // Do not recalculate if no changes! 137 | if (!lightEngine.a()) { 138 | return; 139 | } 140 | 141 | executeSync(lightEngine, new Runnable() { 142 | @Override 143 | public void run() { 144 | if (type == LightType.SKY) { 145 | LightEngineSky les = (LightEngineSky) lightEngine.a(EnumSkyBlock.SKY); 146 | les.a(Integer.MAX_VALUE, true, true); 147 | } else { 148 | LightEngineBlock leb = (LightEngineBlock) lightEngine.a(EnumSkyBlock.BLOCK); 149 | leb.a(Integer.MAX_VALUE, true, true); 150 | } 151 | } 152 | }); 153 | } 154 | 155 | @Override 156 | public void sendChunkSectionsUpdate( 157 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 158 | ) { 159 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 160 | // https://wiki.vg/index.php?title=Pre-release_protocol&oldid=14804#Update_Light 161 | // https://github.com/flori-schwa/VarLight/blob/b9349499f9c9fb995c320f95eae9698dd85aad5c/v1_14_R1/src/me/florian/varlight/nms/v1_14_R1/NmsAdapter_1_14_R1.java#L451 162 | // 163 | // Two last argument is bit-mask what chunk sections to update. Mask containing 164 | // 18 bits, with the lowest bit corresponding to chunk section -1 (in the void, 165 | // y=-16 to y=-1) and the highest bit for chunk section 16 (above the world, 166 | // y=256 to y=271). 167 | PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate( 168 | chunk.getPos(), chunk.e(), sectionsMaskSky, sectionsMaskBlock); 169 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 170 | } 171 | 172 | @Override 173 | public int asSectionMask(int sectionY) { 174 | return 1 << sectionY + 1; 175 | } 176 | 177 | @Override 178 | protected int getViewDistance(Player player) { 179 | return player.getClientViewDistance(); 180 | } 181 | 182 | @SuppressWarnings({"StatementWithEmptyBody", "unchecked"}) 183 | private void executeSync(LightEngineThreaded lightEngine, Runnable task) { 184 | try { 185 | // ##### STEP 1: Pause light engine mailbox to process its tasks. ##### 186 | ThreadedMailbox threadedMailbox = (ThreadedMailbox) lightEngine_ThreadedMailbox 187 | .get(lightEngine); 188 | // State flags bit mask: 189 | // 0x0001 - Closing flag (ThreadedMailbox is closing if non zero). 190 | // 0x0002 - Busy flag (ThreadedMailbox performs a task from queue if non zero). 191 | AtomicInteger stateFlags = (AtomicInteger) threadedMailbox_State.get(threadedMailbox); 192 | int flags; // to hold values from stateFlags 193 | long timeToWait = -1; 194 | // Trying to set bit 1 in state bit mask when it is not set yet. 195 | // This will break the loop in other thread where light engine mailbox processes the taks. 196 | while (!stateFlags.compareAndSet(flags = stateFlags.get() & ~2, flags | 2)) { 197 | if ((flags & 1) != 0) { 198 | // ThreadedMailbox is closing. The light engine mailbox may also stop processing tasks. 199 | // The light engine mailbox can be close due to server shutdown or unloading (closing) the world. 200 | // I am not sure is it unsafe to process our tasks while the world is closing is closing, 201 | // but will try it (one can throw exception here if it crashes the server). 202 | if (timeToWait == -1) { 203 | // Try to wait 3 seconds until light engine mailbox is busy. 204 | timeToWait = System.currentTimeMillis() + 3 * 1000; 205 | Debug.print("ThreadedMailbox is closing. Will wait..."); 206 | } else if (System.currentTimeMillis() >= timeToWait) { 207 | throw new RuntimeException("Failed to enter critical section while ThreadedMailbox is closing"); 208 | } 209 | try { 210 | Thread.sleep(50); 211 | } catch (InterruptedException ignored) { 212 | } 213 | } 214 | } 215 | try { 216 | // ##### STEP 2: Safely running the task while the mailbox process is stopped. ##### 217 | task.run(); 218 | } finally { 219 | // STEP 3: ##### Continue light engine mailbox to process its tasks. ##### 220 | // Firstly: Clearing busy flag to allow ThreadedMailbox to use it for running light engine tasks. 221 | while (!stateFlags.compareAndSet(flags = stateFlags.get(), flags & ~2)) ; 222 | // Secondly: IMPORTANT! The main loop of ThreadedMailbox was broken. Not completed tasks may still be 223 | // in the queue. Therefore, it is important to start the loop again to process tasks from the queue. 224 | // Otherwise, the main server thread may be frozen due to tasks stuck in the queue. 225 | threadedMailbox_DoLoopStep.invoke(threadedMailbox); 226 | } 227 | } catch (InvocationTargetException e) { 228 | throw toRuntimeException(e.getCause()); 229 | } catch (IllegalAccessException e) { 230 | throw toRuntimeException(e); 231 | } 232 | } 233 | 234 | private void lightEngineLayer_a(LightEngineLayer les, BlockPosition var0, int var1) { 235 | try { 236 | LightEngineStorage ls = (LightEngineStorage) lightEngineLayer_c.get(les); 237 | lightEngineStorage_d.invoke(ls); 238 | lightEngineGraph_a.invoke(les, 9223372036854775807L, var0.asLong(), 15 - var1, true); 239 | } catch (InvocationTargetException e) { 240 | throw toRuntimeException(e.getCause()); 241 | } catch (IllegalAccessException e) { 242 | throw toRuntimeException(e); 243 | } 244 | } 245 | 246 | private static RuntimeException toRuntimeException(Throwable e) { 247 | if (e instanceof RuntimeException) { 248 | return (RuntimeException) e; 249 | } 250 | Class cls = e.getClass(); 251 | return new RuntimeException( 252 | String.format("(%s) %s", RuntimeException.class.getPackage().equals(cls.getPackage()) 253 | ? cls.getSimpleName() : cls.getName(), e.getMessage()), 254 | e); 255 | } 256 | 257 | private int getDeltaLight(int x, int dx) { 258 | return (((x ^ ((-dx >> 4) & 15)) + 1) & (-(dx & 1))); 259 | } 260 | 261 | @Override 262 | public List collectChunks( 263 | World world, int blockX, int blockY, int blockZ, LightType lightType, int lightLevel 264 | ) { 265 | if (lightType != LightType.SKY || lightLevel < 15) { 266 | return super.collectChunks(world, blockX, blockY, blockZ, lightType, lightLevel); 267 | } 268 | List list = new ArrayList(); 269 | Collection players = null; 270 | for (int dx = -1; dx <= 1; dx++) { 271 | int lightLevelX = lightLevel - getDeltaLight(blockX & 15, dx); 272 | if (lightLevelX > 0) { 273 | for (int dz = -1; dz <= 1; dz++) { 274 | int lightLevelZ = lightLevelX - getDeltaLight(blockZ & 15, dz); 275 | if (lightLevelZ > 0) { 276 | if (lightLevelZ > getDeltaLight(blockY & 15, 1)) { 277 | int sectionY = (blockY >> 4) + 1; 278 | if (isValidSectionY(world, sectionY)) { 279 | int chunkX = blockX >> 4; 280 | int chunkZ = blockZ >> 4; 281 | ChunkInfo cCoord = new ChunkInfo( 282 | world, 283 | chunkX + dx, 284 | sectionY << 4, 285 | chunkZ + dz, 286 | players != null ? players : (players = world.getPlayers())); 287 | list.add(cCoord); 288 | } 289 | } 290 | for (int sectionY = blockY >> 4; sectionY >= -1; sectionY--) { 291 | if (isValidSectionY(world, sectionY)) { 292 | int chunkX = blockX >> 4; 293 | int chunkZ = blockZ >> 4; 294 | ChunkInfo cCoord = new ChunkInfo( 295 | world, 296 | chunkX + dx, 297 | sectionY << 4, 298 | chunkZ + dz, 299 | players != null ? players : (players = world.getPlayers())); 300 | list.add(cCoord); 301 | } 302 | } 303 | } 304 | } 305 | } 306 | } 307 | return list; 308 | } 309 | 310 | @Override 311 | public boolean isSupported(World world, LightType lightType) { 312 | if (!(world instanceof CraftWorld)) { 313 | return false; 314 | } 315 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 316 | LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 317 | if (lightType == LightType.SKY) { 318 | return lightEngine.a(EnumSkyBlock.SKY) instanceof LightEngineSky; 319 | } else { 320 | return lightEngine.a(EnumSkyBlock.BLOCK) instanceof LightEngineBlock; 321 | } 322 | } 323 | 324 | @Override 325 | public int getMinLightHeight(World world) { 326 | return -16; 327 | } 328 | 329 | @Override 330 | public int getMaxLightHeight(World world) { 331 | return world.getMaxHeight() + 16; 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /nms/v1_16_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_16_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.16.1-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_16_R1/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_16_R1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016-2017 The ImplexDevOne Project 5 | * Copyright (c) 2019 Vladimir Mikhailov 6 | * Copyright (c) 2021 Qveshn 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 27 | 28 | import net.minecraft.server.v1_16_R1.*; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_16_R1.CraftWorld; 31 | import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer; 32 | import org.bukkit.entity.Player; 33 | import ru.beykerykt.lightapi.chunks.ChunkInfo; 34 | import ru.beykerykt.lightapi.LightType; 35 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 36 | import ru.beykerykt.lightapi.utils.Debug; 37 | 38 | import java.lang.reflect.Field; 39 | import java.lang.reflect.InvocationTargetException; 40 | import java.lang.reflect.Method; 41 | import java.util.ArrayList; 42 | import java.util.Collection; 43 | import java.util.List; 44 | import java.util.concurrent.atomic.AtomicInteger; 45 | 46 | public class CraftBukkit_v1_16_R1 extends NmsHandlerBase { 47 | 48 | private Field lightEngine_ThreadedMailbox; 49 | private Field threadedMailbox_State; 50 | private Method threadedMailbox_DoLoopStep; 51 | private Field lightEngineLayer_c; 52 | private Method lightEngineStorage_d; 53 | private Method lightEngineGraph_a; 54 | 55 | public CraftBukkit_v1_16_R1() { 56 | try { 57 | threadedMailbox_DoLoopStep = ThreadedMailbox.class.getDeclaredMethod("f"); 58 | threadedMailbox_DoLoopStep.setAccessible(true); 59 | threadedMailbox_State = ThreadedMailbox.class.getDeclaredField("c"); 60 | threadedMailbox_State.setAccessible(true); 61 | lightEngine_ThreadedMailbox = LightEngineThreaded.class.getDeclaredField("b"); 62 | lightEngine_ThreadedMailbox.setAccessible(true); 63 | 64 | lightEngineLayer_c = LightEngineLayer.class.getDeclaredField("c"); 65 | lightEngineLayer_c.setAccessible(true); 66 | lightEngineStorage_d = LightEngineStorage.class.getDeclaredMethod("d"); 67 | lightEngineStorage_d.setAccessible(true); 68 | lightEngineGraph_a = LightEngineGraph.class.getDeclaredMethod( 69 | "a", long.class, long.class, int.class, boolean.class); 70 | lightEngineGraph_a.setAccessible(true); 71 | } catch (Exception e) { 72 | throw toRuntimeException(e); 73 | } 74 | } 75 | 76 | @Override 77 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 78 | setRawLightLevel(world, lightType, x, y, z, light); 79 | recalculateLighting(world, x, y, z, lightType); 80 | } 81 | 82 | @Override 83 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 84 | setRawLightLevel(world, lightType, x, y, z, 0); 85 | recalculateLighting(world, x, y, z, lightType); 86 | } 87 | 88 | @SuppressWarnings("SameParameterValue") 89 | private void setRawLightLevel(World world, final LightType type, int blockX, int blockY, int blockZ, int lightlevel) { 90 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 91 | final BlockPosition position = new BlockPosition(blockX, blockY, blockZ); 92 | final LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 93 | 94 | final int finalLightLevel = lightlevel < 0 ? 0 : lightlevel > 15 ? 15 : lightlevel; 95 | executeSync(lightEngine, new Runnable() { 96 | @Override 97 | public void run() { 98 | if (type == LightType.SKY) { 99 | LightEngineLayerEventListener layer = lightEngine.a(EnumSkyBlock.SKY); 100 | if (!(layer instanceof LightEngineSky)) return; 101 | LightEngineSky les = (LightEngineSky) layer; 102 | if (finalLightLevel == 0) { 103 | les.a(position); 104 | } else if (les.a(SectionPosition.a(position)) != null) { 105 | try { 106 | lightEngineLayer_a(les, position, finalLightLevel); 107 | } catch (NullPointerException ignore) { 108 | // To prevent problems with the absence of the NibbleArray, even 109 | // if les.a(SectionPosition.a(position)) returns non-null value (corrupted data) 110 | } 111 | } 112 | } else { 113 | LightEngineLayerEventListener layer = lightEngine.a(EnumSkyBlock.BLOCK); 114 | if (!(layer instanceof LightEngineBlock)) return; 115 | LightEngineBlock leb = (LightEngineBlock) layer; 116 | if (finalLightLevel == 0) { 117 | leb.a(position); 118 | } else if (leb.a(SectionPosition.a(position)) != null) { 119 | try { 120 | leb.a(position, finalLightLevel); 121 | } catch (NullPointerException ignore) { 122 | // To prevent problems with the absence of the NibbleArray, even 123 | // if leb.a(SectionPosition.a(position)) returns non-null value (corrupted data) 124 | } 125 | } 126 | } 127 | } 128 | }); 129 | } 130 | 131 | @Override 132 | protected void recalculateLighting(World world, int blockX, int blockY, int blockZ, final LightType type) { 133 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 134 | final LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 135 | 136 | // Do not recalculate if no changes! 137 | if (!lightEngine.a()) { 138 | return; 139 | } 140 | 141 | executeSync(lightEngine, new Runnable() { 142 | @Override 143 | public void run() { 144 | if (type == LightType.SKY) { 145 | LightEngineSky les = (LightEngineSky) lightEngine.a(EnumSkyBlock.SKY); 146 | les.a(Integer.MAX_VALUE, true, true); 147 | } else { 148 | LightEngineBlock leb = (LightEngineBlock) lightEngine.a(EnumSkyBlock.BLOCK); 149 | leb.a(Integer.MAX_VALUE, true, true); 150 | } 151 | } 152 | }); 153 | } 154 | 155 | @Override 156 | public void sendChunkSectionsUpdate( 157 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 158 | ) { 159 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 160 | // https://wiki.vg/index.php?title=Pre-release_protocol&oldid=14804#Update_Light 161 | // https://github.com/flori-schwa/VarLight/blob/b9349499f9c9fb995c320f95eae9698dd85aad5c/v1_14_R1/src/me/florian/varlight/nms/v1_14_R1/NmsAdapter_1_14_R1.java#L451 162 | // 163 | // Two last argument is bit-mask what chunk sections to update. Mask containing 164 | // 18 bits, with the lowest bit corresponding to chunk section -1 (in the void, 165 | // y=-16 to y=-1) and the highest bit for chunk section 16 (above the world, 166 | // y=256 to y=271). 167 | PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate( 168 | chunk.getPos(), chunk.e(), sectionsMaskSky, sectionsMaskBlock, true); 169 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 170 | } 171 | 172 | @Override 173 | public int asSectionMask(int sectionY) { 174 | return 1 << sectionY + 1; 175 | } 176 | 177 | @Override 178 | protected int getViewDistance(Player player) { 179 | return player.getClientViewDistance(); 180 | } 181 | 182 | @SuppressWarnings({"StatementWithEmptyBody", "unchecked"}) 183 | private void executeSync(LightEngineThreaded lightEngine, Runnable task) { 184 | try { 185 | // ##### STEP 1: Pause light engine mailbox to process its tasks. ##### 186 | ThreadedMailbox threadedMailbox = (ThreadedMailbox) lightEngine_ThreadedMailbox 187 | .get(lightEngine); 188 | // State flags bit mask: 189 | // 0x0001 - Closing flag (ThreadedMailbox is closing if non zero). 190 | // 0x0002 - Busy flag (ThreadedMailbox performs a task from queue if non zero). 191 | AtomicInteger stateFlags = (AtomicInteger) threadedMailbox_State.get(threadedMailbox); 192 | int flags; // to hold values from stateFlags 193 | long timeToWait = -1; 194 | // Trying to set bit 1 in state bit mask when it is not set yet. 195 | // This will break the loop in other thread where light engine mailbox processes the taks. 196 | while (!stateFlags.compareAndSet(flags = stateFlags.get() & ~2, flags | 2)) { 197 | if ((flags & 1) != 0) { 198 | // ThreadedMailbox is closing. The light engine mailbox may also stop processing tasks. 199 | // The light engine mailbox can be close due to server shutdown or unloading (closing) the world. 200 | // I am not sure is it unsafe to process our tasks while the world is closing is closing, 201 | // but will try it (one can throw exception here if it crashes the server). 202 | if (timeToWait == -1) { 203 | // Try to wait 3 seconds until light engine mailbox is busy. 204 | timeToWait = System.currentTimeMillis() + 3 * 1000; 205 | Debug.print("ThreadedMailbox is closing. Will wait..."); 206 | } else if (System.currentTimeMillis() >= timeToWait) { 207 | throw new RuntimeException("Failed to enter critical section while ThreadedMailbox is closing"); 208 | } 209 | try { 210 | Thread.sleep(50); 211 | } catch (InterruptedException ignored) { 212 | } 213 | } 214 | } 215 | try { 216 | // ##### STEP 2: Safely running the task while the mailbox process is stopped. ##### 217 | task.run(); 218 | } finally { 219 | // STEP 3: ##### Continue light engine mailbox to process its tasks. ##### 220 | // Firstly: Clearing busy flag to allow ThreadedMailbox to use it for running light engine tasks. 221 | while (!stateFlags.compareAndSet(flags = stateFlags.get(), flags & ~2)) ; 222 | // Secondly: IMPORTANT! The main loop of ThreadedMailbox was broken. Not completed tasks may still be 223 | // in the queue. Therefore, it is important to start the loop again to process tasks from the queue. 224 | // Otherwise, the main server thread may be frozen due to tasks stuck in the queue. 225 | threadedMailbox_DoLoopStep.invoke(threadedMailbox); 226 | } 227 | } catch (InvocationTargetException e) { 228 | throw toRuntimeException(e.getCause()); 229 | } catch (IllegalAccessException e) { 230 | throw toRuntimeException(e); 231 | } 232 | } 233 | 234 | private void lightEngineLayer_a(LightEngineLayer les, BlockPosition var0, int var1) { 235 | try { 236 | LightEngineStorage ls = (LightEngineStorage) lightEngineLayer_c.get(les); 237 | lightEngineStorage_d.invoke(ls); 238 | lightEngineGraph_a.invoke(les, 9223372036854775807L, var0.asLong(), 15 - var1, true); 239 | } catch (InvocationTargetException e) { 240 | throw toRuntimeException(e.getCause()); 241 | } catch (IllegalAccessException e) { 242 | throw toRuntimeException(e); 243 | } 244 | } 245 | 246 | private static RuntimeException toRuntimeException(Throwable e) { 247 | if (e instanceof RuntimeException) { 248 | return (RuntimeException) e; 249 | } 250 | Class cls = e.getClass(); 251 | return new RuntimeException( 252 | String.format("(%s) %s", RuntimeException.class.getPackage().equals(cls.getPackage()) 253 | ? cls.getSimpleName() : cls.getName(), e.getMessage()), 254 | e); 255 | } 256 | 257 | private int getDeltaLight(int x, int dx) { 258 | return (((x ^ ((-dx >> 4) & 15)) + 1) & (-(dx & 1))); 259 | } 260 | 261 | @Override 262 | public List collectChunks( 263 | World world, int blockX, int blockY, int blockZ, LightType lightType, int lightLevel 264 | ) { 265 | if (lightType != LightType.SKY || lightLevel < 15) { 266 | return super.collectChunks(world, blockX, blockY, blockZ, lightType, lightLevel); 267 | } 268 | List list = new ArrayList(); 269 | Collection players = null; 270 | for (int dx = -1; dx <= 1; dx++) { 271 | int lightLevelX = lightLevel - getDeltaLight(blockX & 15, dx); 272 | if (lightLevelX > 0) { 273 | for (int dz = -1; dz <= 1; dz++) { 274 | int lightLevelZ = lightLevelX - getDeltaLight(blockZ & 15, dz); 275 | if (lightLevelZ > 0) { 276 | if (lightLevelZ > getDeltaLight(blockY & 15, 1)) { 277 | int sectionY = (blockY >> 4) + 1; 278 | if (isValidSectionY(world, sectionY)) { 279 | int chunkX = blockX >> 4; 280 | int chunkZ = blockZ >> 4; 281 | ChunkInfo cCoord = new ChunkInfo( 282 | world, 283 | chunkX + dx, 284 | sectionY << 4, 285 | chunkZ + dz, 286 | players != null ? players : (players = world.getPlayers())); 287 | list.add(cCoord); 288 | } 289 | } 290 | for (int sectionY = blockY >> 4; sectionY >= -1; sectionY--) { 291 | if (isValidSectionY(world, sectionY)) { 292 | int chunkX = blockX >> 4; 293 | int chunkZ = blockZ >> 4; 294 | ChunkInfo cCoord = new ChunkInfo( 295 | world, 296 | chunkX + dx, 297 | sectionY << 4, 298 | chunkZ + dz, 299 | players != null ? players : (players = world.getPlayers())); 300 | list.add(cCoord); 301 | } 302 | } 303 | } 304 | } 305 | } 306 | } 307 | return list; 308 | } 309 | 310 | @Override 311 | public boolean isSupported(World world, LightType lightType) { 312 | if (!(world instanceof CraftWorld)) { 313 | return false; 314 | } 315 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 316 | LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 317 | if (lightType == LightType.SKY) { 318 | return lightEngine.a(EnumSkyBlock.SKY) instanceof LightEngineSky; 319 | } else { 320 | return lightEngine.a(EnumSkyBlock.BLOCK) instanceof LightEngineBlock; 321 | } 322 | } 323 | 324 | @Override 325 | public int getMinLightHeight(World world) { 326 | return -16; 327 | } 328 | 329 | @Override 330 | public int getMaxLightHeight(World world) { 331 | return world.getMaxHeight() + 16; 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /nms/v1_16_R2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_16_R2 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.16.3-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_16_R2/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_16_R2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016-2017 The ImplexDevOne Project 5 | * Copyright (c) 2019 Vladimir Mikhailov 6 | * Copyright (c) 2021 Qveshn 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 27 | 28 | import net.minecraft.server.v1_16_R2.*; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_16_R2.CraftWorld; 31 | import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer; 32 | import org.bukkit.entity.Player; 33 | import ru.beykerykt.lightapi.chunks.ChunkInfo; 34 | import ru.beykerykt.lightapi.LightType; 35 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 36 | import ru.beykerykt.lightapi.utils.Debug; 37 | 38 | import java.lang.reflect.Field; 39 | import java.lang.reflect.InvocationTargetException; 40 | import java.lang.reflect.Method; 41 | import java.util.ArrayList; 42 | import java.util.Collection; 43 | import java.util.List; 44 | import java.util.concurrent.atomic.AtomicInteger; 45 | 46 | public class CraftBukkit_v1_16_R2 extends NmsHandlerBase { 47 | 48 | private Field lightEngine_ThreadedMailbox; 49 | private Field threadedMailbox_State; 50 | private Method threadedMailbox_DoLoopStep; 51 | private Field lightEngineLayer_c; 52 | private Method lightEngineStorage_d; 53 | private Method lightEngineGraph_a; 54 | 55 | public CraftBukkit_v1_16_R2() { 56 | try { 57 | threadedMailbox_DoLoopStep = ThreadedMailbox.class.getDeclaredMethod("f"); 58 | threadedMailbox_DoLoopStep.setAccessible(true); 59 | threadedMailbox_State = ThreadedMailbox.class.getDeclaredField("c"); 60 | threadedMailbox_State.setAccessible(true); 61 | lightEngine_ThreadedMailbox = LightEngineThreaded.class.getDeclaredField("b"); 62 | lightEngine_ThreadedMailbox.setAccessible(true); 63 | 64 | lightEngineLayer_c = LightEngineLayer.class.getDeclaredField("c"); 65 | lightEngineLayer_c.setAccessible(true); 66 | lightEngineStorage_d = LightEngineStorage.class.getDeclaredMethod("d"); 67 | lightEngineStorage_d.setAccessible(true); 68 | lightEngineGraph_a = LightEngineGraph.class.getDeclaredMethod( 69 | "a", long.class, long.class, int.class, boolean.class); 70 | lightEngineGraph_a.setAccessible(true); 71 | } catch (Exception e) { 72 | throw toRuntimeException(e); 73 | } 74 | } 75 | 76 | @Override 77 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 78 | setRawLightLevel(world, lightType, x, y, z, light); 79 | recalculateLighting(world, x, y, z, lightType); 80 | } 81 | 82 | @Override 83 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 84 | setRawLightLevel(world, lightType, x, y, z, 0); 85 | recalculateLighting(world, x, y, z, lightType); 86 | } 87 | 88 | @SuppressWarnings("SameParameterValue") 89 | private void setRawLightLevel(World world, final LightType type, int blockX, int blockY, int blockZ, int lightlevel) { 90 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 91 | final BlockPosition position = new BlockPosition(blockX, blockY, blockZ); 92 | final LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 93 | 94 | final int finalLightLevel = lightlevel < 0 ? 0 : lightlevel > 15 ? 15 : lightlevel; 95 | executeSync(lightEngine, new Runnable() { 96 | @Override 97 | public void run() { 98 | if (type == LightType.SKY) { 99 | LightEngineLayerEventListener layer = lightEngine.a(EnumSkyBlock.SKY); 100 | if (!(layer instanceof LightEngineSky)) return; 101 | LightEngineSky les = (LightEngineSky) layer; 102 | if (finalLightLevel == 0) { 103 | les.a(position); 104 | } else if (les.a(SectionPosition.a(position)) != null) { 105 | try { 106 | lightEngineLayer_a(les, position, finalLightLevel); 107 | } catch (NullPointerException ignore) { 108 | // To prevent problems with the absence of the NibbleArray, even 109 | // if les.a(SectionPosition.a(position)) returns non-null value (corrupted data) 110 | } 111 | } 112 | } else { 113 | LightEngineLayerEventListener layer = lightEngine.a(EnumSkyBlock.BLOCK); 114 | if (!(layer instanceof LightEngineBlock)) return; 115 | LightEngineBlock leb = (LightEngineBlock) layer; 116 | if (finalLightLevel == 0) { 117 | leb.a(position); 118 | } else if (leb.a(SectionPosition.a(position)) != null) { 119 | try { 120 | leb.a(position, finalLightLevel); 121 | } catch (NullPointerException ignore) { 122 | // To prevent problems with the absence of the NibbleArray, even 123 | // if leb.a(SectionPosition.a(position)) returns non-null value (corrupted data) 124 | } 125 | } 126 | } 127 | } 128 | }); 129 | } 130 | 131 | @Override 132 | protected void recalculateLighting(World world, int blockX, int blockY, int blockZ, final LightType type) { 133 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 134 | final LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 135 | 136 | // Do not recalculate if no changes! 137 | if (!lightEngine.a()) { 138 | return; 139 | } 140 | 141 | executeSync(lightEngine, new Runnable() { 142 | @Override 143 | public void run() { 144 | if (type == LightType.SKY) { 145 | LightEngineSky les = (LightEngineSky) lightEngine.a(EnumSkyBlock.SKY); 146 | les.a(Integer.MAX_VALUE, true, true); 147 | } else { 148 | LightEngineBlock leb = (LightEngineBlock) lightEngine.a(EnumSkyBlock.BLOCK); 149 | leb.a(Integer.MAX_VALUE, true, true); 150 | } 151 | } 152 | }); 153 | } 154 | 155 | @Override 156 | public void sendChunkSectionsUpdate( 157 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 158 | ) { 159 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 160 | // https://wiki.vg/index.php?title=Pre-release_protocol&oldid=14804#Update_Light 161 | // https://github.com/flori-schwa/VarLight/blob/b9349499f9c9fb995c320f95eae9698dd85aad5c/v1_14_R1/src/me/florian/varlight/nms/v1_14_R1/NmsAdapter_1_14_R1.java#L451 162 | // 163 | // Two last argument is bit-mask what chunk sections to update. Mask containing 164 | // 18 bits, with the lowest bit corresponding to chunk section -1 (in the void, 165 | // y=-16 to y=-1) and the highest bit for chunk section 16 (above the world, 166 | // y=256 to y=271). 167 | PacketPlayOutLightUpdate packet = new PacketPlayOutLightUpdate( 168 | chunk.getPos(), chunk.e(), sectionsMaskSky, sectionsMaskBlock, true); 169 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 170 | } 171 | 172 | @Override 173 | public int asSectionMask(int sectionY) { 174 | return 1 << sectionY + 1; 175 | } 176 | 177 | @Override 178 | protected int getViewDistance(Player player) { 179 | return player.getClientViewDistance(); 180 | } 181 | 182 | @SuppressWarnings({"StatementWithEmptyBody", "unchecked"}) 183 | private void executeSync(LightEngineThreaded lightEngine, Runnable task) { 184 | try { 185 | // ##### STEP 1: Pause light engine mailbox to process its tasks. ##### 186 | ThreadedMailbox threadedMailbox = (ThreadedMailbox) lightEngine_ThreadedMailbox 187 | .get(lightEngine); 188 | // State flags bit mask: 189 | // 0x0001 - Closing flag (ThreadedMailbox is closing if non zero). 190 | // 0x0002 - Busy flag (ThreadedMailbox performs a task from queue if non zero). 191 | AtomicInteger stateFlags = (AtomicInteger) threadedMailbox_State.get(threadedMailbox); 192 | int flags; // to hold values from stateFlags 193 | long timeToWait = -1; 194 | // Trying to set bit 1 in state bit mask when it is not set yet. 195 | // This will break the loop in other thread where light engine mailbox processes the taks. 196 | while (!stateFlags.compareAndSet(flags = stateFlags.get() & ~2, flags | 2)) { 197 | if ((flags & 1) != 0) { 198 | // ThreadedMailbox is closing. The light engine mailbox may also stop processing tasks. 199 | // The light engine mailbox can be close due to server shutdown or unloading (closing) the world. 200 | // I am not sure is it unsafe to process our tasks while the world is closing is closing, 201 | // but will try it (one can throw exception here if it crashes the server). 202 | if (timeToWait == -1) { 203 | // Try to wait 3 seconds until light engine mailbox is busy. 204 | timeToWait = System.currentTimeMillis() + 3 * 1000; 205 | Debug.print("ThreadedMailbox is closing. Will wait..."); 206 | } else if (System.currentTimeMillis() >= timeToWait) { 207 | throw new RuntimeException("Failed to enter critical section while ThreadedMailbox is closing"); 208 | } 209 | try { 210 | Thread.sleep(50); 211 | } catch (InterruptedException ignored) { 212 | } 213 | } 214 | } 215 | try { 216 | // ##### STEP 2: Safely running the task while the mailbox process is stopped. ##### 217 | task.run(); 218 | } finally { 219 | // STEP 3: ##### Continue light engine mailbox to process its tasks. ##### 220 | // Firstly: Clearing busy flag to allow ThreadedMailbox to use it for running light engine tasks. 221 | while (!stateFlags.compareAndSet(flags = stateFlags.get(), flags & ~2)) ; 222 | // Secondly: IMPORTANT! The main loop of ThreadedMailbox was broken. Not completed tasks may still be 223 | // in the queue. Therefore, it is important to start the loop again to process tasks from the queue. 224 | // Otherwise, the main server thread may be frozen due to tasks stuck in the queue. 225 | threadedMailbox_DoLoopStep.invoke(threadedMailbox); 226 | } 227 | } catch (InvocationTargetException e) { 228 | throw toRuntimeException(e.getCause()); 229 | } catch (IllegalAccessException e) { 230 | throw toRuntimeException(e); 231 | } 232 | } 233 | 234 | private void lightEngineLayer_a(LightEngineLayer les, BlockPosition var0, int var1) { 235 | try { 236 | LightEngineStorage ls = (LightEngineStorage) lightEngineLayer_c.get(les); 237 | lightEngineStorage_d.invoke(ls); 238 | lightEngineGraph_a.invoke(les, 9223372036854775807L, var0.asLong(), 15 - var1, true); 239 | } catch (InvocationTargetException e) { 240 | throw toRuntimeException(e.getCause()); 241 | } catch (IllegalAccessException e) { 242 | throw toRuntimeException(e); 243 | } 244 | } 245 | 246 | private static RuntimeException toRuntimeException(Throwable e) { 247 | if (e instanceof RuntimeException) { 248 | return (RuntimeException) e; 249 | } 250 | Class cls = e.getClass(); 251 | return new RuntimeException( 252 | String.format("(%s) %s", RuntimeException.class.getPackage().equals(cls.getPackage()) 253 | ? cls.getSimpleName() : cls.getName(), e.getMessage()), 254 | e); 255 | } 256 | 257 | private int getDeltaLight(int x, int dx) { 258 | return (((x ^ ((-dx >> 4) & 15)) + 1) & (-(dx & 1))); 259 | } 260 | 261 | @Override 262 | public List collectChunks( 263 | World world, int blockX, int blockY, int blockZ, LightType lightType, int lightLevel 264 | ) { 265 | if (lightType != LightType.SKY || lightLevel < 15) { 266 | return super.collectChunks(world, blockX, blockY, blockZ, lightType, lightLevel); 267 | } 268 | List list = new ArrayList(); 269 | Collection players = null; 270 | for (int dx = -1; dx <= 1; dx++) { 271 | int lightLevelX = lightLevel - getDeltaLight(blockX & 15, dx); 272 | if (lightLevelX > 0) { 273 | for (int dz = -1; dz <= 1; dz++) { 274 | int lightLevelZ = lightLevelX - getDeltaLight(blockZ & 15, dz); 275 | if (lightLevelZ > 0) { 276 | if (lightLevelZ > getDeltaLight(blockY & 15, 1)) { 277 | int sectionY = (blockY >> 4) + 1; 278 | if (isValidSectionY(world, sectionY)) { 279 | int chunkX = blockX >> 4; 280 | int chunkZ = blockZ >> 4; 281 | ChunkInfo cCoord = new ChunkInfo( 282 | world, 283 | chunkX + dx, 284 | sectionY << 4, 285 | chunkZ + dz, 286 | players != null ? players : (players = world.getPlayers())); 287 | list.add(cCoord); 288 | } 289 | } 290 | for (int sectionY = blockY >> 4; sectionY >= -1; sectionY--) { 291 | if (isValidSectionY(world, sectionY)) { 292 | int chunkX = blockX >> 4; 293 | int chunkZ = blockZ >> 4; 294 | ChunkInfo cCoord = new ChunkInfo( 295 | world, 296 | chunkX + dx, 297 | sectionY << 4, 298 | chunkZ + dz, 299 | players != null ? players : (players = world.getPlayers())); 300 | list.add(cCoord); 301 | } 302 | } 303 | } 304 | } 305 | } 306 | } 307 | return list; 308 | } 309 | 310 | @Override 311 | public boolean isSupported(World world, LightType lightType) { 312 | if (!(world instanceof CraftWorld)) { 313 | return false; 314 | } 315 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 316 | LightEngineThreaded lightEngine = worldServer.getChunkProvider().getLightEngine(); 317 | if (lightType == LightType.SKY) { 318 | return lightEngine.a(EnumSkyBlock.SKY) instanceof LightEngineSky; 319 | } else { 320 | return lightEngine.a(EnumSkyBlock.BLOCK) instanceof LightEngineBlock; 321 | } 322 | } 323 | 324 | @Override 325 | public int getMinLightHeight(World world) { 326 | return -16; 327 | } 328 | 329 | @Override 330 | public int getMaxLightHeight(World world) { 331 | return world.getMaxHeight() + 16; 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /nms/v1_16_R3/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_16_R3 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.16.5-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_17_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_17_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.17.1-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_8_R3/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_8_R3 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.8.8-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_8_R3/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_8_R3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Vladimir Mikhailov 5 | * Copyright (c) 2020 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 26 | 27 | import net.minecraft.server.v1_8_R3.*; 28 | import org.bukkit.World; 29 | import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; 30 | import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; 31 | import org.bukkit.entity.Player; 32 | import ru.beykerykt.lightapi.LightType; 33 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 34 | 35 | public class CraftBukkit_v1_8_R3 extends NmsHandlerBase { 36 | 37 | @Override 38 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 39 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 40 | worldServer.a(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, 41 | new BlockPosition(x, y, z), light); 42 | recalculateNeighbours(world, x, y, z, lightType); 43 | } 44 | 45 | @Override 46 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 47 | recalculateLighting(world, x, y, z, lightType); 48 | } 49 | 50 | @Override 51 | protected void recalculateLighting(World world, int x, int y, int z, LightType lightType) { 52 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 53 | BlockPosition position = new BlockPosition(x, y, z); 54 | worldServer.c(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, position); 55 | } 56 | 57 | @Override 58 | public void sendChunkSectionsUpdate( 59 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 60 | ) { 61 | int sectionsMask = sectionsMaskSky | sectionsMaskBlock; 62 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 63 | // The last argument is bit-mask what chunk sections to update. Mask containing 64 | // 16 bits, with the lowest bit corresponding to chunk section 0 (y=0 to y=15) 65 | // and the highest bit for chunk section 15 (y=240 to 255). 66 | PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(chunk, false, sectionsMask); 67 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 68 | } 69 | 70 | @Override 71 | public boolean isSupported(World world, LightType lightType) { 72 | if (!(world instanceof CraftWorld)) { 73 | return false; 74 | } 75 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 76 | if (lightType == LightType.SKY) { 77 | return !worldServer.worldProvider.o(); 78 | } else { 79 | return true; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /nms/v1_9_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_9_R1 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.9-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_9_R1/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_9_R1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Vladimir Mikhailov 5 | * Copyright (c) 2020 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 26 | 27 | import net.minecraft.server.v1_9_R1.*; 28 | import org.bukkit.World; 29 | import org.bukkit.craftbukkit.v1_9_R1.CraftWorld; 30 | import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; 31 | import org.bukkit.entity.Player; 32 | import ru.beykerykt.lightapi.LightType; 33 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 34 | 35 | public class CraftBukkit_v1_9_R1 extends NmsHandlerBase { 36 | 37 | @Override 38 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 39 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 40 | worldServer.a(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, 41 | new BlockPosition(x, y, z), light); 42 | recalculateNeighbours(world, x, y, z, lightType); 43 | } 44 | 45 | @Override 46 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 47 | recalculateLighting(world, x, y, z, lightType); 48 | } 49 | 50 | @Override 51 | protected void recalculateLighting(World world, int x, int y, int z, LightType lightType) { 52 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 53 | BlockPosition position = new BlockPosition(x, y, z); 54 | worldServer.c(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, position); 55 | } 56 | 57 | @Override 58 | public void sendChunkSectionsUpdate( 59 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 60 | ) { 61 | int sectionsMask = sectionsMaskSky | sectionsMaskBlock; 62 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 63 | // The last argument is bit-mask what chunk sections to update. Mask containing 64 | // 16 bits, with the lowest bit corresponding to chunk section 0 (y=0 to y=15) 65 | // and the highest bit for chunk section 15 (y=240 to 255). 66 | PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(chunk, false, sectionsMask); 67 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 68 | } 69 | 70 | @Override 71 | public boolean isSupported(World world, LightType lightType) { 72 | if (!(world instanceof CraftWorld)) { 73 | return false; 74 | } 75 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 76 | if (lightType == LightType.SKY) { 77 | return !worldServer.worldProvider.m(); 78 | } else { 79 | return true; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /nms/v1_9_R2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi.nms 8 | v1_9_R2 9 | 3.3.0 10 | 11 | 12 | true 13 | 1.8 14 | 1.8 15 | UTF-8 16 | 17 | 18 | 19 | 20 | org.bukkit 21 | craftbukkit 22 | 1.9.4-R0.1-SNAPSHOT 23 | 24 | 25 | ru.beykerykt.lightapi 26 | common 27 | 3.3.0 28 | 29 | 30 | -------------------------------------------------------------------------------- /nms/v1_9_R2/src/main/java/ru/beykerykt/lightapi/server/nms/craftbukkit/CraftBukkit_v1_9_R2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Vladimir Mikhailov 5 | * Copyright (c) 2020 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.server.nms.craftbukkit; 26 | 27 | import net.minecraft.server.v1_9_R2.*; 28 | import org.bukkit.World; 29 | import org.bukkit.craftbukkit.v1_9_R2.CraftWorld; 30 | import org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer; 31 | import org.bukkit.entity.Player; 32 | import ru.beykerykt.lightapi.LightType; 33 | import ru.beykerykt.lightapi.server.nms.NmsHandlerBase; 34 | 35 | public class CraftBukkit_v1_9_R2 extends NmsHandlerBase { 36 | 37 | @Override 38 | public void createLight(World world, int x, int y, int z, LightType lightType, int light) { 39 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 40 | worldServer.a(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, 41 | new BlockPosition(x, y, z), light); 42 | recalculateNeighbours(world, x, y, z, lightType); 43 | } 44 | 45 | @Override 46 | public void deleteLight(World world, int x, int y, int z, LightType lightType) { 47 | recalculateLighting(world, x, y, z, lightType); 48 | } 49 | 50 | @Override 51 | protected void recalculateLighting(World world, int x, int y, int z, LightType lightType) { 52 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 53 | BlockPosition position = new BlockPosition(x, y, z); 54 | worldServer.c(lightType == LightType.SKY ? EnumSkyBlock.SKY : EnumSkyBlock.BLOCK, position); 55 | } 56 | 57 | @Override 58 | public void sendChunkSectionsUpdate( 59 | World world, int chunkX, int chunkZ, int sectionsMaskSky, int sectionsMaskBlock, Player player 60 | ) { 61 | int sectionsMask = sectionsMaskSky | sectionsMaskBlock; 62 | Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(chunkX, chunkZ); 63 | // The last argument is bit-mask what chunk sections to update. Mask containing 64 | // 16 bits, with the lowest bit corresponding to chunk section 0 (y=0 to y=15) 65 | // and the highest bit for chunk section 15 (y=240 to 255). 66 | PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(chunk, sectionsMask); 67 | ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); 68 | } 69 | 70 | @Override 71 | public boolean isSupported(World world, LightType lightType) { 72 | if (!(world instanceof CraftWorld)) { 73 | return false; 74 | } 75 | WorldServer worldServer = ((CraftWorld) world).getHandle(); 76 | if (lightType == LightType.SKY) { 77 | return !worldServer.worldProvider.m(); 78 | } else { 79 | return true; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /others/LIGHT_API_LOGO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qveshn/LightAPI/1f284fa30086a090eb4be71141bf8551e5a3a7ac/others/LIGHT_API_LOGO.png -------------------------------------------------------------------------------- /others/LIGHT_API_LOGO.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qveshn/LightAPI/1f284fa30086a090eb4be71141bf8551e5a3a7ac/others/LIGHT_API_LOGO.psd -------------------------------------------------------------------------------- /others/light_api_logo_version_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qveshn/LightAPI/1f284fa30086a090eb4be71141bf8551e5a3a7ac/others/light_api_logo_version_2.png -------------------------------------------------------------------------------- /others/light_api_logo_version_2.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qveshn/LightAPI/1f284fa30086a090eb4be71141bf8551e5a3a7ac/others/light_api_logo_version_2.psd -------------------------------------------------------------------------------- /others/light_api_logo_version_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qveshn/LightAPI/1f284fa30086a090eb4be71141bf8551e5a3a7ac/others/light_api_logo_version_3.png -------------------------------------------------------------------------------- /others/light_api_logo_version_3.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qveshn/LightAPI/1f284fa30086a090eb4be71141bf8551e5a3a7ac/others/light_api_logo_version_3.psd -------------------------------------------------------------------------------- /others/torch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qveshn/LightAPI/1f284fa30086a090eb4be71141bf8551e5a3a7ac/others/torch.png -------------------------------------------------------------------------------- /plugin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt 8 | LightAPI-fork 9 | 3.5.2 10 | 11 | 12 | 1.8 13 | 1.8 14 | UTF-8 15 | 16 | 17 | 18 | 19 | ru.beykerykt.lightapi 20 | common 21 | 3.3.0 22 | 23 | 24 | ru.beykerykt.lightapi.nms 25 | v1_17_R1 26 | 3.3.0 27 | 28 | 29 | ru.beykerykt.lightapi.nms 30 | v1_16_R3 31 | 3.3.0 32 | 33 | 34 | ru.beykerykt.lightapi.nms 35 | v1_16_R2 36 | 3.3.0 37 | 38 | 39 | ru.beykerykt.lightapi.nms 40 | v1_16_R1 41 | 3.3.0 42 | 43 | 44 | ru.beykerykt.lightapi.nms 45 | v1_15_R1 46 | 3.3.0 47 | 48 | 49 | ru.beykerykt.lightapi.nms 50 | v1_14_R1 51 | 3.3.0 52 | 53 | 54 | ru.beykerykt.lightapi.nms 55 | v1_13_R2 56 | 3.3.0 57 | 58 | 59 | ru.beykerykt.lightapi.nms 60 | v1_13_R1 61 | 3.3.0 62 | 63 | 64 | ru.beykerykt.lightapi.nms 65 | v1_12_R1 66 | 3.3.0 67 | 68 | 69 | ru.beykerykt.lightapi.nms 70 | v1_11_R1 71 | 3.3.0 72 | 73 | 74 | ru.beykerykt.lightapi.nms 75 | v1_10_R1 76 | 3.3.0 77 | 78 | 79 | ru.beykerykt.lightapi.nms 80 | v1_9_R2 81 | 3.3.0 82 | 83 | 84 | ru.beykerykt.lightapi.nms 85 | v1_9_R1 86 | 3.3.0 87 | 88 | 89 | ru.beykerykt.lightapi.nms 90 | v1_8_R3 91 | 3.3.0 92 | 93 | 94 | 95 | 96 | 97 | 98 | true 99 | src/main/resources 100 | 101 | plugin.yml 102 | 103 | 104 | 105 | ${project.basedir}/.. 106 | 107 | LICENSE 108 | 109 | 110 | 111 | src/main/resources 112 | 113 | config.yml 114 | 115 | 116 | 117 | 118 | 119 | org.apache.maven.plugins 120 | maven-jar-plugin 121 | 3.1.2 122 | 123 | 124 | false 125 | 126 | false 127 | 128 | 129 | 130 | 131 | 132 | org.apache.maven.plugins 133 | maven-dependency-plugin 134 | 135 | 136 | copy-dependencies 137 | prepare-package 138 | 139 | unpack-dependencies 140 | 141 | 142 | ${project.build.outputDirectory} 143 | true 144 | META-INF/** 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/chunks/ChunkLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Qveshn 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.chunks; 25 | 26 | import org.bukkit.World; 27 | 28 | public class ChunkLocation { 29 | private final World world; 30 | private final int x; 31 | private final int z; 32 | 33 | public ChunkLocation(World world, int x, int z) { 34 | this.world = world; 35 | this.x = x; 36 | this.z = z; 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | final int prime = 31; 42 | int result = 1; 43 | result = prime * result + ((world == null) ? 0 : world.hashCode()); 44 | result = prime * result + x; 45 | result = prime * result + z; 46 | return result; 47 | } 48 | 49 | public World getWorld() { 50 | return world; 51 | } 52 | 53 | public int getX() { 54 | return x; 55 | } 56 | 57 | public int getZ() { 58 | return z; 59 | } 60 | 61 | @Override 62 | public boolean equals(Object obj) { 63 | if (this == obj) { 64 | return true; 65 | } 66 | if (obj == null) { 67 | return false; 68 | } 69 | if (!(obj instanceof ChunkLocation)) { 70 | return false; 71 | } 72 | ChunkLocation other = (ChunkLocation) obj; 73 | if (world == null) { 74 | if (other.world != null) { 75 | return false; 76 | } 77 | } else if (!world.getName().equals(other.world.getName())) { 78 | return false; 79 | } 80 | return x == other.x && z == other.z; 81 | } 82 | 83 | @Override 84 | public String toString() { 85 | return "ChunkCoords [world=" + (world == null ? null : world.getName()) + ", x=" + x + ", z=" + z + "]"; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/chunks/ChunkUpdateInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 LOOHP 5 | * Copyright (c) 2021 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.chunks; 26 | 27 | import org.bukkit.entity.Player; 28 | import ru.beykerykt.lightapi.LightType; 29 | 30 | import java.util.BitSet; 31 | import java.util.Collection; 32 | import java.util.HashSet; 33 | 34 | public class ChunkUpdateInfo { 35 | 36 | private BitSet sectionMaskSky = new BitSet(); 37 | private BitSet sectionMaskBlock = new BitSet(); 38 | private Collection players = new HashSet(); 39 | 40 | public void add(LightType lightType, BitSet sectionMask, Collection players) { 41 | if (lightType == LightType.SKY) { 42 | this.sectionMaskSky.or(sectionMask); 43 | } else { 44 | this.sectionMaskBlock.or(sectionMask); 45 | } 46 | add(players); 47 | } 48 | 49 | private void add(Collection players) { 50 | this.players.addAll(players); 51 | } 52 | 53 | public Collection getPlayers() { 54 | return players; 55 | } 56 | 57 | public BitSet getSectionMaskSky() { 58 | return sectionMaskSky; 59 | } 60 | 61 | public BitSet getSectionMaskBlock() { 62 | return sectionMaskBlock; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/events/DeleteLightEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * Copyright (c) 2019 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.events; 26 | 27 | import org.bukkit.World; 28 | import org.bukkit.event.Cancellable; 29 | import org.bukkit.event.Event; 30 | import org.bukkit.event.HandlerList; 31 | import ru.beykerykt.lightapi.LightType; 32 | 33 | public class DeleteLightEvent extends Event implements Cancellable { 34 | 35 | private boolean cancel; 36 | private static final HandlerList handlers = new HandlerList(); 37 | private World world; 38 | private int x; 39 | private int y; 40 | private int z; 41 | private LightType lightType; 42 | private boolean async; 43 | 44 | @Deprecated 45 | public DeleteLightEvent(World world, int x, int y, int z, boolean async) { 46 | this(world, x, y, z, LightType.BLOCK, async); 47 | } 48 | 49 | public DeleteLightEvent(World world, int x, int y, int z, LightType lightType, boolean async) { 50 | this.world = world; 51 | this.x = x; 52 | this.y = y; 53 | this.z = z; 54 | this.lightType = lightType; 55 | this.async = async; 56 | } 57 | 58 | @Override 59 | public HandlerList getHandlers() { 60 | return handlers; 61 | } 62 | 63 | public static HandlerList getHandlerList() { 64 | return handlers; 65 | } 66 | 67 | @Override 68 | public boolean isCancelled() { 69 | return cancel; 70 | } 71 | 72 | @Override 73 | public void setCancelled(boolean arg0) { 74 | this.cancel = arg0; 75 | } 76 | 77 | public int getX() { 78 | return x; 79 | } 80 | 81 | public void setX(int x) { 82 | this.x = x; 83 | } 84 | 85 | public int getY() { 86 | return y; 87 | } 88 | 89 | public void setY(int y) { 90 | this.y = y; 91 | } 92 | 93 | public int getZ() { 94 | return z; 95 | } 96 | 97 | public void setZ(int z) { 98 | this.z = z; 99 | } 100 | 101 | public World getWorld() { 102 | return world; 103 | } 104 | 105 | public void setWorld(World world) { 106 | this.world = world; 107 | } 108 | 109 | public boolean isAsync() { 110 | return async; 111 | } 112 | 113 | public void setAsync(boolean flag) { 114 | this.async = flag; 115 | } 116 | 117 | public LightType getLightType() { 118 | return lightType; 119 | } 120 | 121 | public void setLightType(LightType lightType) { 122 | this.lightType = lightType; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/events/SetLightEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * Copyright (c) 2019 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.events; 26 | 27 | import org.bukkit.World; 28 | import org.bukkit.event.Cancellable; 29 | import org.bukkit.event.Event; 30 | import org.bukkit.event.HandlerList; 31 | import ru.beykerykt.lightapi.LightType; 32 | 33 | public class SetLightEvent extends Event implements Cancellable { 34 | 35 | private boolean cancel; 36 | private static final HandlerList handlers = new HandlerList(); 37 | private World world; 38 | private int x; 39 | private int y; 40 | private int z; 41 | private LightType lightType; 42 | private int level; 43 | private boolean async; 44 | 45 | @Deprecated 46 | public SetLightEvent(World world, int x, int y, int z, int level, boolean async) { 47 | this(world, x, y, z, LightType.BLOCK, level, async); 48 | } 49 | 50 | public SetLightEvent(World world, int x, int y, int z, LightType lightType, int level, boolean async) { 51 | this.world = world; 52 | this.x = x; 53 | this.y = y; 54 | this.z = z; 55 | this.lightType = lightType; 56 | this.level = level; 57 | this.async = async; 58 | } 59 | 60 | @Override 61 | public HandlerList getHandlers() { 62 | return handlers; 63 | } 64 | 65 | public static HandlerList getHandlerList() { 66 | return handlers; 67 | } 68 | 69 | @Override 70 | public boolean isCancelled() { 71 | return cancel; 72 | } 73 | 74 | @Override 75 | public void setCancelled(boolean arg0) { 76 | this.cancel = arg0; 77 | } 78 | 79 | public int getLightLevel() { 80 | return level; 81 | } 82 | 83 | public void setLightLevel(int level) { 84 | this.level = level; 85 | } 86 | 87 | public int getX() { 88 | return x; 89 | } 90 | 91 | public void setX(int x) { 92 | this.x = x; 93 | } 94 | 95 | public int getY() { 96 | return y; 97 | } 98 | 99 | public void setY(int y) { 100 | this.y = y; 101 | } 102 | 103 | public int getZ() { 104 | return z; 105 | } 106 | 107 | public void setZ(int z) { 108 | this.z = z; 109 | } 110 | 111 | public World getWorld() { 112 | return world; 113 | } 114 | 115 | public void setWorld(World world) { 116 | this.world = world; 117 | } 118 | 119 | public boolean isAsync() { 120 | return async; 121 | } 122 | 123 | public void setAsync(boolean flag) { 124 | this.async = flag; 125 | } 126 | 127 | public LightType getLightType() { 128 | return lightType; 129 | } 130 | 131 | public void setLightType(LightType lightType) { 132 | this.lightType = lightType; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/events/UpdateChunkEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * Copyright (c) 2019 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.events; 26 | 27 | import org.bukkit.event.Cancellable; 28 | import org.bukkit.event.Event; 29 | import org.bukkit.event.HandlerList; 30 | 31 | import ru.beykerykt.lightapi.chunks.ChunkInfo; 32 | import ru.beykerykt.lightapi.LightType; 33 | 34 | public class UpdateChunkEvent extends Event implements Cancellable { 35 | 36 | private boolean cancel; 37 | private static final HandlerList handlers = new HandlerList(); 38 | private ChunkInfo cCoord; 39 | private LightType lightType; 40 | 41 | public UpdateChunkEvent(ChunkInfo cCoord) { 42 | this(cCoord, LightType.BLOCK); 43 | } 44 | 45 | public UpdateChunkEvent(ChunkInfo cCoord, LightType lightType) { 46 | this.cCoord = cCoord; 47 | this.lightType = lightType; 48 | } 49 | 50 | @Override 51 | public HandlerList getHandlers() { 52 | return handlers; 53 | } 54 | 55 | public static HandlerList getHandlerList() { 56 | return handlers; 57 | } 58 | 59 | @Override 60 | public boolean isCancelled() { 61 | return cancel; 62 | } 63 | 64 | @Override 65 | public void setCancelled(boolean arg0) { 66 | this.cancel = arg0; 67 | } 68 | 69 | public ChunkInfo getChunkInfo() { 70 | return cCoord; 71 | } 72 | 73 | public void setChunkInfo(ChunkInfo cCoord) { 74 | this.cCoord = cCoord; 75 | } 76 | 77 | public LightType getLightType() { 78 | return lightType; 79 | } 80 | 81 | public void setLightType(LightType lightType) { 82 | this.lightType = lightType; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/request/RequestSteamMachine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * Copyright (c) 2021 LOOHP 6 | * Copyright (c) 2021 Qveshn 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in all 16 | * copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | package ru.beykerykt.lightapi.request; 27 | 28 | import org.bukkit.World; 29 | import org.bukkit.entity.Player; 30 | import ru.beykerykt.lightapi.chunks.ChunkInfo; 31 | import ru.beykerykt.lightapi.chunks.ChunkLocation; 32 | import ru.beykerykt.lightapi.chunks.ChunkUpdateInfo; 33 | import ru.beykerykt.lightapi.server.ServerModManager; 34 | import ru.beykerykt.lightapi.server.nms.INMSHandler; 35 | import ru.beykerykt.lightapi.LightType; 36 | import ru.beykerykt.lightapi.utils.Debug; 37 | 38 | import java.util.*; 39 | import java.util.concurrent.*; 40 | 41 | public class RequestSteamMachine implements Runnable { 42 | 43 | private boolean isStarted; 44 | private Queue REQUEST_QUEUE = new ConcurrentLinkedQueue(); 45 | private int maxIterationsPerTick; 46 | private Map chunksToUpdate = new HashMap(); 47 | 48 | // THREADS 49 | private ScheduledFuture sch; 50 | private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 51 | 52 | public void start(int ticks, int maxIterationsPerTick) { 53 | if (!isStarted) { 54 | this.maxIterationsPerTick = maxIterationsPerTick; 55 | sch = executor.scheduleWithFixedDelay(this, 0, 50 * ticks, TimeUnit.MILLISECONDS); 56 | isStarted = true; 57 | } 58 | } 59 | 60 | public void shutdown() { 61 | if (isStarted) { 62 | REQUEST_QUEUE.clear(); 63 | maxIterationsPerTick = 0; 64 | sch.cancel(false); 65 | isStarted = false; 66 | } 67 | } 68 | 69 | @SuppressWarnings("unused") 70 | public boolean isStarted() { 71 | return isStarted; 72 | } 73 | 74 | @SuppressWarnings("UnusedReturnValue") 75 | public boolean addToQueue(Runnable request) { 76 | if (request != null) { 77 | REQUEST_QUEUE.add(request); 78 | return true; 79 | } 80 | return false; 81 | } 82 | 83 | public void addChunkToUpdate(final ChunkInfo info, final LightType lightType, Collection receivers) { 84 | int SectionY = info.getChunkY(); 85 | World world = info.getWorld(); 86 | INMSHandler nmsHandler = ServerModManager.getNMSHandler(); 87 | if (nmsHandler.isValidSectionY(world, SectionY)) { 88 | final ChunkLocation chunk = new ChunkLocation(info.getWorld(), info.getChunkX(), info.getChunkZ()); 89 | final BitSet sectionYMask = nmsHandler.asSectionMask(world, SectionY); 90 | final Collection players = new ArrayList( 91 | receivers != null ? receivers : info.getReceivers() 92 | ); 93 | addToQueue(new Runnable() { 94 | @Override 95 | public void run() { 96 | ChunkUpdateInfo chunkUpdateInfo = chunksToUpdate.get(chunk); 97 | if (chunkUpdateInfo == null) { 98 | chunksToUpdate.put(chunk, chunkUpdateInfo = new ChunkUpdateInfo()); 99 | } 100 | chunkUpdateInfo.add(lightType, sectionYMask, players); 101 | } 102 | }); 103 | } 104 | } 105 | 106 | @Override 107 | public void run() { 108 | try { 109 | boolean debug = Debug.isEnabled(); 110 | int totalSends = 0; 111 | int totalSections = 0; 112 | Set usedPlayers = null; 113 | int iterationsCount = 0; 114 | if (debug) { 115 | usedPlayers = new HashSet(); 116 | } 117 | 118 | Runnable request; 119 | while (iterationsCount < maxIterationsPerTick && (request = REQUEST_QUEUE.poll()) != null) { 120 | request.run(); 121 | iterationsCount++; 122 | } 123 | 124 | INMSHandler nmsHandler = ServerModManager.getNMSHandler(); 125 | 126 | for (Map.Entry item : chunksToUpdate.entrySet()) { 127 | ChunkLocation chunk = item.getKey(); 128 | ChunkUpdateInfo chunkUpdateInfo = item.getValue(); 129 | BitSet sectionMaskSky = chunkUpdateInfo.getSectionMaskSky(); 130 | BitSet sectionMaskBlock = chunkUpdateInfo.getSectionMaskBlock(); 131 | Collection players = nmsHandler.filterVisiblePlayers( 132 | chunk.getWorld(), chunk.getX(), chunk.getZ(), chunkUpdateInfo.getPlayers()); 133 | nmsHandler.sendChunkSectionsUpdate(chunk.getWorld(), chunk.getX(), chunk.getZ(), 134 | sectionMaskSky, sectionMaskBlock, players); 135 | if (debug) { 136 | totalSends += players.size(); 137 | BitSet clone = (BitSet) sectionMaskSky.clone(); 138 | clone.or(sectionMaskBlock); 139 | totalSections += clone.cardinality(); 140 | usedPlayers.addAll(players); 141 | } 142 | } 143 | 144 | if (debug && (iterationsCount > 0 || chunksToUpdate.size() > 0)) { 145 | Debug.print("requests %d/%d, chunks = %d, total sends = %d, players = %d, total sections = %d", 146 | iterationsCount, 147 | REQUEST_QUEUE.size(), 148 | chunksToUpdate.size(), 149 | totalSends, 150 | usedPlayers.size(), 151 | totalSections 152 | ); 153 | } 154 | } catch (Throwable e) { 155 | e.printStackTrace(); 156 | } finally { 157 | chunksToUpdate.clear(); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/server/ServerModInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.server; 25 | 26 | import java.util.Map; 27 | import java.util.concurrent.ConcurrentHashMap; 28 | 29 | import ru.beykerykt.lightapi.server.nms.INMSHandler; 30 | 31 | public class ServerModInfo { 32 | 33 | private String modName; 34 | private Map> versions; 35 | 36 | public ServerModInfo(String modname) { 37 | this.modName = modname; 38 | this.versions = new ConcurrentHashMap>(); 39 | } 40 | 41 | public String getModName() { 42 | return modName; 43 | } 44 | 45 | public Map> getVersions() { 46 | return versions; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/server/ServerModManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2017 Vladimir Mikhailov 5 | * Copyright (c) 2021 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.server; 26 | 27 | import ru.beykerykt.lightapi.server.nms.INMSHandler; 28 | import ru.beykerykt.lightapi.utils.Utils; 29 | 30 | import java.util.Map; 31 | import java.util.concurrent.ConcurrentHashMap; 32 | 33 | public class ServerModManager { 34 | 35 | private static Map supportImpl = new ConcurrentHashMap(); 36 | private static INMSHandler handler; 37 | 38 | public static Class findImplementaion(String modName) { 39 | ServerModInfo impl = supportImpl.get(modName); 40 | return impl != null ? impl.getVersions().get(Utils.serverVersion()) : null; 41 | } 42 | 43 | public static void initImplementaion(Class clazz) throws Exception { 44 | ServerModManager.handler = clazz.getConstructor().newInstance(); 45 | } 46 | 47 | public static void shutdown() { 48 | if (isInitialized()) { 49 | handler = null; 50 | } 51 | } 52 | 53 | public static boolean isInitialized() { 54 | return handler != null; 55 | } 56 | 57 | public static boolean registerServerMod(ServerModInfo info) { 58 | if (supportImpl.containsKey(info.getModName())) { 59 | return false; 60 | } 61 | supportImpl.put(info.getModName(), info); 62 | return true; 63 | } 64 | 65 | public static boolean unregisterServerMod(String modName) { 66 | if (supportImpl.containsKey(modName)) { 67 | return false; 68 | } 69 | supportImpl.remove(modName); 70 | return true; 71 | } 72 | 73 | public static INMSHandler getNMSHandler() { 74 | return handler; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/updater/Response.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.updater; 25 | 26 | /** 27 | * Enumeration of possible responses from the updater. 28 | * 29 | * @author Connor Spencer Harries 30 | */ 31 | public enum Response { 32 | 33 | /** 34 | * GitHub could not find the repository. 35 | */ 36 | REPO_NOT_FOUND, 37 | 38 | /** 39 | * The latest release on GitHub isn't semver compliant. 40 | */ 41 | REPO_NOT_SEMVER, 42 | 43 | /** 44 | * No releases have been made on the repository. 45 | */ 46 | REPO_NO_RELEASES, 47 | 48 | /** 49 | * An update has been found. 50 | */ 51 | SUCCESS, 52 | 53 | /** 54 | * An error occured whilst trying to find updates. 55 | */ 56 | FAILED, 57 | 58 | /** 59 | * GitHub denied the connection. This is most likely due to too many connections being opened to the API 60 | * within a small period of time. 61 | */ 62 | GITHUB_DENY, 63 | 64 | /** 65 | * Used to indicate a server error such as HTTP status code 500. 66 | */ 67 | GITHUB_ERROR, 68 | 69 | /** 70 | * The specified version is already the latest version 71 | */ 72 | NO_UPDATE; 73 | 74 | @Override 75 | public String toString() { 76 | return this.name(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/updater/UpdateType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.updater; 25 | 26 | import org.bukkit.ChatColor; 27 | import ru.beykerykt.lightapi.LightAPI; 28 | 29 | import java.util.regex.Matcher; 30 | 31 | public enum UpdateType { 32 | OUTDATE(ChatColor.GRAY + "Outdate"), 33 | MAJOR(ChatColor.RED + "Major"), 34 | MINOR(ChatColor.YELLOW + "Minor"), 35 | PATCH(ChatColor.GREEN + "Patch"); 36 | 37 | private String name; 38 | 39 | UpdateType(String name) { 40 | this.name = name; 41 | } 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public static UpdateType compareVersion(String newVersion) { 48 | Integer[] pluginMatcher = getMatchers(LightAPI.getInstance().getDescription().getVersion()); 49 | Integer[] updateMatcher = getMatchers(newVersion); 50 | 51 | if (pluginMatcher[0] < updateMatcher[0]) { 52 | return UpdateType.MAJOR; 53 | } 54 | 55 | if (pluginMatcher[1] < updateMatcher[1]) { 56 | return UpdateType.MINOR; 57 | } 58 | 59 | if (pluginMatcher[2] < updateMatcher[2]) { 60 | return UpdateType.PATCH; 61 | } 62 | 63 | return UpdateType.OUTDATE; 64 | } 65 | 66 | public static Integer[] getMatchers(String version) { 67 | Matcher matcher = Updater.regex.matcher(version); 68 | Integer[] list = new Integer[3]; 69 | if (matcher.matches()) { 70 | list[0] = Integer.parseInt(matcher.group(1)); 71 | list[1] = Integer.parseInt(matcher.group(2)); 72 | list[2] = Integer.parseInt(matcher.group(3)); 73 | } 74 | return list; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/updater/Updater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.updater; 25 | 26 | import org.json.simple.JSONArray; 27 | import org.json.simple.JSONObject; 28 | import org.json.simple.JSONValue; 29 | 30 | import java.io.BufferedReader; 31 | import java.io.InputStreamReader; 32 | import java.net.MalformedURLException; 33 | import java.net.URL; 34 | import java.net.URLConnection; 35 | import java.util.logging.Level; 36 | import java.util.regex.Pattern; 37 | 38 | /** 39 | * Class that tries to find updates on a GitHub repository. 40 | * 41 | * @author Connor Spencer Harries 42 | * @version 1.0.2 43 | */ 44 | @SuppressWarnings("unused") 45 | public class Updater { 46 | 47 | /** 48 | * Pattern used to match semantic versioning compliant strings. 49 | *

50 | * Major: matcher.group(1) Minor: matcher.group(2) Patch: matcher.group(3) 51 | *

52 | * Does detect suffixes such as RC though they're unused as of now. 53 | */ 54 | static Pattern regex = Pattern.compile( 55 | "(?:[v]?)([0-9]+)\\.([0-9]+)\\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z-]+)?", 56 | Pattern.CASE_INSENSITIVE); 57 | 58 | /** 59 | * URL template for all API calls 60 | */ 61 | private static final String api = "https://api.github.com/repos/{{ REPOSITORY }}/releases"; 62 | 63 | /** 64 | * Store the query result. 65 | */ 66 | private Response result = Response.NO_UPDATE; 67 | 68 | /** 69 | * User agent to use when making requests, according to the API it's preferred if this is your username. 70 | *

71 | * See https://developer.github.com/v3/#user-agent-required 72 | */ 73 | private final String agent = "Albioncode"; 74 | 75 | /** 76 | * Store the repository to lookup. 77 | */ 78 | private final String repository; 79 | 80 | /** 81 | * Should I print to System.out? 82 | */ 83 | private final boolean verbose; 84 | 85 | /** 86 | * Store the latest version. 87 | */ 88 | private Version version; 89 | 90 | /** 91 | * Store the version passed in the constructor. 92 | */ 93 | private Version current; 94 | 95 | /** 96 | * Thread that does the heavy lifting. 97 | */ 98 | private Thread thread; 99 | 100 | /** 101 | * URL to query. 102 | */ 103 | private URL url; 104 | 105 | // BeYkeRYkt 106 | private String body; 107 | 108 | /** 109 | * Create a new {@link Updater} using integers as the major, minor and patch. 110 | * 111 | * @param major current major 112 | * @param minor current minor 113 | * @param patch current patch 114 | * @param repository github repository to query 115 | */ 116 | public Updater(int major, int minor, int patch, String repository) throws Exception { 117 | this(Version.parse(major + "." + minor + "." + patch), repository, false); 118 | } 119 | 120 | /** 121 | * Create a new {@link Updater} using integers as the major, minor and patch. 122 | * 123 | * @param major current major 124 | * @param minor current minor 125 | * @param patch current patch 126 | * @param repository github repository to query 127 | */ 128 | public Updater(int major, int minor, int patch, String repository, boolean verbose) throws Exception { 129 | this(Version.parse(major + "." + minor + "." + patch), repository, verbose); 130 | } 131 | 132 | /** 133 | * Create a new {@link Updater} using a {@link java.lang.String} 134 | * 135 | * @param version string containing valid semver string 136 | * @param repository github repository to query 137 | * @throws Exception error whilst parsing semver string 138 | */ 139 | public Updater(String version, String repository) throws Exception { 140 | this(Version.parse(version), repository, false); 141 | } 142 | 143 | /** 144 | * Create a new {@link Updater} using a {@link java.lang.String} 145 | * 146 | * @param version string containing valid semver string 147 | * @param repository github repository to query 148 | * @param verbose print information to System.out 149 | * @throws Exception error whilst parsing semver string 150 | */ 151 | public Updater(String version, String repository, boolean verbose) throws Exception { 152 | this(Version.parse(version), repository, verbose); 153 | } 154 | 155 | /** 156 | * Create a new {@link Updater} using a {@link ru.beykerykt.lightapi.updater.Version} object. 157 | * 158 | * @param repository github repository to query 159 | */ 160 | public Updater(Version version, String repository) throws Exception { 161 | this(version, repository, false); 162 | } 163 | 164 | /** 165 | * Create a new {@link Updater} using a {@link java.lang.String} 166 | * 167 | * @param version string containing valid semver string 168 | * @param repository github repository to query 169 | * @param verbose print information to console 170 | * @throws Exception error whilst parsing semver string 171 | */ 172 | public Updater(Version version, String repository, boolean verbose) throws Exception { 173 | if (version == null) { 174 | throw new Exception("Provided version is not semver compliant!"); 175 | } 176 | 177 | this.repository = repository; 178 | this.current = version; 179 | this.verbose = verbose; 180 | 181 | try { 182 | this.url = new URL(api.replace("{{ REPOSITORY }}", this.repository)); 183 | log(Level.INFO, "Set the URL to get"); 184 | } catch (NumberFormatException ex) { 185 | log(Level.SEVERE, "Unable to parse semver string!"); 186 | throw new Exception("Unable to parse semver string!"); 187 | } catch (MalformedURLException ex) { 188 | log(Level.SEVERE, "Invalid URL, return failed response."); 189 | result = Response.FAILED; 190 | throw new Exception(ex.getMessage()); 191 | } 192 | 193 | if (this.result != Response.FAILED) { 194 | this.thread = new Thread(new UpdaterRunnable(this)); 195 | this.thread.start(); 196 | } 197 | } 198 | 199 | /** 200 | * Actually lookup the JSON data. 201 | */ 202 | private void run() { 203 | try { 204 | final URLConnection connection = url.openConnection(); 205 | connection.setConnectTimeout(6000); 206 | 207 | connection.addRequestProperty("Accept", "application/vnd.github.v3+json"); 208 | log(Level.INFO, "Opening connection to API"); 209 | 210 | final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 211 | final StringBuilder buffer = new StringBuilder(); 212 | 213 | String line; 214 | while ((line = reader.readLine()) != null) { 215 | buffer.append(line); 216 | } 217 | 218 | JSONArray releases = (JSONArray) JSONValue.parse(buffer.toString()); 219 | log(Level.INFO, "Parsing the returned JSON"); 220 | 221 | if (releases.isEmpty()) { 222 | log(Level.WARNING, "Appears there were no releases, setting result"); 223 | this.result = Response.REPO_NO_RELEASES; 224 | return; 225 | } 226 | 227 | JSONObject release = (JSONObject) releases.get(0); 228 | String tag = release.get("tag_name").toString(); 229 | 230 | // BeYkeRYkt 231 | String body = release.get("body").toString(); 232 | 233 | if (isSemver(tag)) { 234 | this.version = Version.parse(tag); 235 | // BeYkeRYkt 236 | this.body = body; 237 | 238 | if (version != null && current.compare(version)) { 239 | log(Level.INFO, "Hooray, we found a semver compliant update!"); 240 | this.result = Response.SUCCESS; 241 | } else { 242 | log(Level.INFO, "The version you specified is the latest version available!"); 243 | this.result = Response.NO_UPDATE; 244 | } 245 | } else { 246 | log(Level.WARNING, "Version string is not semver compliant!"); 247 | this.result = Response.REPO_NOT_SEMVER; 248 | } 249 | } catch (Exception e) { 250 | if (e.getMessage().contains("HTTP response code: 403")) { 251 | log(Level.WARNING, "GitHub denied our HTTP request!"); 252 | this.result = Response.GITHUB_DENY; 253 | } else if (e.getMessage().contains("HTTP response code: 404")) { 254 | log(Level.WARNING, "The specified repository could not be found!"); 255 | this.result = Response.REPO_NOT_FOUND; 256 | } else if (e.getMessage().contains("HTTP response code: 500")) { 257 | log(Level.WARNING, "Internal server error"); 258 | this.result = Response.GITHUB_ERROR; 259 | } else { 260 | log(Level.SEVERE, "Failed to check for updates!"); 261 | this.result = Response.FAILED; 262 | this.version = null; 263 | } 264 | } 265 | } 266 | 267 | private void exit(Response response) { 268 | if (response != Response.SUCCESS) { 269 | this.result = response; 270 | this.version = null; 271 | } 272 | } 273 | 274 | /** 275 | * @return {@link java.lang.String} the version that GitHub tells us about. 276 | */ 277 | public String getLatestVersion() { 278 | waitForThread(); 279 | 280 | if (version == null) { 281 | log(Level.INFO, "Latest version is undefined, return message."); 282 | return "Please check #getResult()"; 283 | } 284 | 285 | log(Level.INFO, "Somebody queried the latest version"); 286 | return version.toString(); 287 | } 288 | 289 | /** 290 | * @return {@link ru.beykerykt.lightapi.updater.Response} 291 | */ 292 | public Response getResult() { 293 | log(Level.INFO, "Somebody queried the update result"); 294 | waitForThread(); 295 | return this.result; 296 | } 297 | 298 | /** 299 | * @return the update repository 300 | */ 301 | public String getRepository() { 302 | log(Level.INFO, "Somebody queried the repository"); 303 | return this.repository; 304 | } 305 | 306 | /** 307 | * Try and wait for the thread to finish executing. 308 | */ 309 | private void waitForThread() { 310 | if ((this.thread != null) && this.thread.isAlive()) { 311 | try { 312 | this.thread.join(); 313 | log(Level.INFO, "Trying to join thread"); 314 | } catch (final InterruptedException e) { 315 | e.printStackTrace(); 316 | } 317 | } 318 | } 319 | 320 | /** 321 | * Test if the version string contains a valid semver string 322 | * 323 | * @param version version to test 324 | * @return true if valid 325 | */ 326 | @SuppressWarnings("WeakerAccess") 327 | public static boolean isSemver(String version) { 328 | return regex.matcher(version).matches(); 329 | } 330 | 331 | private void log(Level level, String message) { 332 | if (this.verbose) { 333 | String msg = String.format("[%s] %s", level.toString().toUpperCase(), message); 334 | if (level != Level.SEVERE) { 335 | System.out.println(msg); 336 | } else { 337 | System.err.println(msg); 338 | } 339 | } 340 | } 341 | 342 | // BeYkeRYkt 343 | public String getChanges() { 344 | return body; 345 | } 346 | 347 | public Version getVersion() { 348 | waitForThread(); 349 | if (version == null) { 350 | log(Level.INFO, "Latest version is undefined, return message."); 351 | return null; 352 | } 353 | 354 | log(Level.INFO, "Somebody queried the latest version"); 355 | return version; 356 | } 357 | } 358 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/updater/UpdaterRunnable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.updater; 25 | 26 | import java.lang.reflect.Method; 27 | 28 | /** 29 | * Simple solution to stop the main thread being blocked 30 | * 31 | * @author Connor Spencer Harries 32 | */ 33 | public class UpdaterRunnable implements Runnable { 34 | 35 | /** 36 | * Store the parent {@link Updater} instance. 37 | */ 38 | private final Updater updater; 39 | 40 | /** 41 | * Create a new {@link ru.beykerykt.lightapi.updater.UpdaterRunnable} with an {@link Updater} as the parent. 42 | * 43 | * @param parent instace of {@link Updater} 44 | */ 45 | UpdaterRunnable(Updater parent) { 46 | this.updater = parent; 47 | } 48 | 49 | /** 50 | * Use reflection to invoke the run method on our {@link Updater} 51 | */ 52 | @Override 53 | public void run() { 54 | try { 55 | Method method = updater.getClass().getDeclaredMethod("run"); 56 | method.setAccessible(true); 57 | 58 | method.invoke(updater); 59 | 60 | method.setAccessible(false); 61 | } catch (Throwable e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/updater/Version.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package ru.beykerykt.lightapi.updater; 25 | 26 | import java.util.regex.Matcher; 27 | 28 | /** 29 | * Simple major.minor.patch storage system with getters. 30 | * 31 | * @author Connor Spencer Harries 32 | */ 33 | public class Version { 34 | 35 | /** 36 | * Store the version major. 37 | */ 38 | private final int major; 39 | 40 | /** 41 | * Store the version minor. 42 | */ 43 | private final int minor; 44 | 45 | /** 46 | * Store the version patch. 47 | */ 48 | private final int patch; 49 | 50 | /** 51 | * Create a new instance of the {@link ru.beykerykt.lightapi.updater.Version} class. 52 | * 53 | * @param major semver major 54 | * @param minor semver minor 55 | * @param patch semver patch 56 | */ 57 | @SuppressWarnings("WeakerAccess") 58 | public Version(int major, int minor, int patch) { 59 | this.major = major; 60 | this.minor = minor; 61 | this.patch = patch; 62 | } 63 | 64 | /** 65 | * Quick method for parsing version strings and matching them using the {@link java.util.regex.Pattern} in {@link Updater} 66 | * 67 | * @param version semver string to parse 68 | * @return {@link ru.beykerykt.lightapi.updater.Version} if valid semver string 69 | */ 70 | public static Version parse(String version) { 71 | Matcher matcher = Updater.regex.matcher(version); 72 | 73 | if (matcher.matches()) { 74 | int x = Integer.parseInt(matcher.group(1)); 75 | int y = Integer.parseInt(matcher.group(2)); 76 | int z = Integer.parseInt(matcher.group(3)); 77 | 78 | return new Version(x, y, z); 79 | } 80 | 81 | return null; 82 | } 83 | 84 | /** 85 | * @return semver major 86 | */ 87 | @SuppressWarnings("WeakerAccess") 88 | public int getMajor() { 89 | return major; 90 | } 91 | 92 | /** 93 | * @return semver minor 94 | */ 95 | @SuppressWarnings("WeakerAccess") 96 | public int getMinor() { 97 | return minor; 98 | } 99 | 100 | /** 101 | * @return semver patch 102 | */ 103 | @SuppressWarnings("WeakerAccess") 104 | public int getPatch() { 105 | return patch; 106 | } 107 | 108 | /** 109 | * @return joined version string. 110 | */ 111 | @Override 112 | public String toString() { 113 | return major + "." + minor + "." + patch; 114 | } 115 | 116 | /** 117 | * Little method to see if the input version is greater than ours. 118 | * 119 | * @param version input {@link ru.beykerykt.lightapi.updater.Version} object 120 | * @return true if the version is greater than ours 121 | */ 122 | @SuppressWarnings("WeakerAccess") 123 | public boolean compare(Version version) { 124 | int result = version.getMajor() - this.getMajor(); 125 | if (result == 0) { 126 | result = version.getMinor() - this.getMinor(); 127 | if (result == 0) { 128 | result = version.getPatch() - this.getPatch(); 129 | } 130 | } 131 | return result > 0; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/beykerykt/lightapi/utils/BungeeChatHelperClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 Vladimir Mikhailov 5 | * Copyright (c) 2021 Qveshn 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | package ru.beykerykt.lightapi.utils; 26 | 27 | import net.md_5.bungee.api.chat.BaseComponent; 28 | import net.md_5.bungee.api.chat.ClickEvent; 29 | import net.md_5.bungee.api.chat.ComponentBuilder; 30 | import net.md_5.bungee.api.chat.HoverEvent; 31 | import net.md_5.bungee.api.chat.TextComponent; 32 | import org.bukkit.entity.Player; 33 | import ru.beykerykt.lightapi.LightAPI; 34 | 35 | public class BungeeChatHelperClass { 36 | 37 | public static boolean hasBungeeChatAPI() { 38 | try { 39 | Class clazz = Class.forName("net.md_5.bungee.api.chat.TextComponent"); 40 | if (clazz != null) { 41 | return true; 42 | } 43 | } catch (ClassNotFoundException e) { 44 | e.printStackTrace(); 45 | } 46 | return false; 47 | } 48 | 49 | public static void sendMessageTitle(Player player, LightAPI plugin) { 50 | TextComponent title = new TextComponent("§b-------< §eLightAPI-fork "); 51 | TextComponent version = new TextComponent("§f" + plugin.getDescription().getVersion()); 52 | version.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/lightapi update")); 53 | version.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 54 | new ComponentBuilder("Click here for check update\n§7/lightapi update").create())); 55 | title.addExtra(version); 56 | title.addExtra(new TextComponent(" §b>-------")); 57 | sendMessage(player, title, plugin); 58 | } 59 | 60 | public static void sendMessageAboutPlugin(Player player, LightAPI plugin) { 61 | sendMessageTitle(player, plugin); 62 | 63 | plugin.sendMessage(player, "§bDevelopers: §f%s", LightAPI.join("§7, §f", plugin.getDescription().getAuthors())); 64 | plugin.sendMessage(player, "§bSource code: §f%s", LightAPI.sourceCodeUrl); 65 | TextComponent licensed = new TextComponent("§bLicensed under "); 66 | TextComponent MIT = new TextComponent("§fMIT License"); 67 | MIT.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://opensource.org/licenses/MIT/")); 68 | MIT.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 69 | new ComponentBuilder("Goto for information about license!").create())); 70 | licensed.addExtra(MIT); 71 | sendMessage(player, licensed, plugin); 72 | 73 | plugin.printServerInfo(player); 74 | 75 | TextComponent text = new TextComponent("§e§l<"); 76 | TextComponent sourcecode = new TextComponent("§6Source code"); 77 | sourcecode.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, LightAPI.sourceCodeUrl)); 78 | sourcecode.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 79 | new ComponentBuilder("Goto the GitHub!").create())); 80 | text.addExtra(sourcecode); 81 | text.addExtra(new TextComponent("§e§l> <")); 82 | 83 | TextComponent developer = new TextComponent("§6Developer"); 84 | developer.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, LightAPI.authorUrl)); 85 | developer.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 86 | new ComponentBuilder("§f" + LightAPI.author).create())); 87 | text.addExtra(developer); 88 | text.addExtra(new TextComponent("§e§l> <")); 89 | 90 | TextComponent contributors = new TextComponent("§6Contributors"); 91 | contributors.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, LightAPI.contributorsUrl)); 92 | contributors.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 93 | new ComponentBuilder("ALIENS!!").create())); 94 | text.addExtra(contributors); 95 | text.addExtra(new TextComponent("§e§l> <")); 96 | 97 | TextComponent checkUpdate = new TextComponent("§6Check update"); 98 | checkUpdate.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/lightapi update")); 99 | checkUpdate.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 100 | new ComponentBuilder("Click here for check update\n§7/lightapi update").create())); 101 | text.addExtra(checkUpdate); 102 | text.addExtra(new TextComponent("§e§l>")); 103 | sendMessage(player, text, plugin); 104 | } 105 | 106 | private static void sendMessage(Player player, BaseComponent component, LightAPI plugin) { 107 | BaseComponent prefix = new TextComponent(plugin.messagePrefix()); 108 | prefix.addExtra(component); 109 | player.spigot().sendMessage(prefix); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /plugin/src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # LightAPI configuration 2 | version: 3 3 | update-delay-ticks: 2 4 | max-iterations-per-tick: 400 5 | updater: 6 | enable: true 7 | repo: Qveshn/LightAPI 8 | update-delay-ticks: 40 9 | view-changelog: false 10 | debug: false 11 | colored-log: true 12 | message-prefix: '' 13 | -------------------------------------------------------------------------------- /plugin/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: LightAPI 2 | main: ru.beykerykt.lightapi.LightAPI 3 | version: ${project.version} 4 | api-version: '1.13' 5 | description: Bukkit Library for create invisible light source 6 | authors: [ BeYkeRYkt, Qveshn ] 7 | commands: 8 | lightapi: 9 | description: Main command 10 | permissions: 11 | lightapi.updater: 12 | default: false -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | ru.beykerykt.lightapi 8 | LightAPI-parent 9 | 1.0.0 10 | pom 11 | 12 | 13 | true 14 | 15 | 16 | 17 | plugin 18 | common 19 | nms/v1_8_R3 20 | nms/v1_9_R1 21 | nms/v1_9_R2 22 | nms/v1_10_R1 23 | nms/v1_11_R1 24 | nms/v1_12_R1 25 | nms/v1_13_R1 26 | nms/v1_13_R2 27 | nms/v1_14_R1 28 | nms/v1_15_R1 29 | nms/v1_16_R1 30 | nms/v1_16_R2 31 | nms/v1_16_R3 32 | nms/v1_17_R1 33 | 34 | 35 | --------------------------------------------------------------------------------