├── .gitignore ├── CHANGELOG.md ├── EffectLib.doxyfile ├── LICENSE ├── README.md ├── TODO.md ├── pom.xml └── src └── main ├── java └── de │ └── slikey │ └── effectlib │ ├── Effect.java │ ├── EffectLib.java │ ├── EffectManager.java │ ├── EffectType.java │ ├── effect │ ├── AnimatedBallEffect.java │ ├── ArcEffect.java │ ├── AtomEffect.java │ ├── BigBangEffect.java │ ├── BleedEffect.java │ ├── CircleEffect.java │ ├── CloudEffect.java │ ├── ColoredImageEffect.java │ ├── ConeEffect.java │ ├── CubeEffect.java │ ├── CuboidEffect.java │ ├── CylinderEffect.java │ ├── DiscoBallEffect.java │ ├── DnaEffect.java │ ├── DonutEffect.java │ ├── DragonEffect.java │ ├── EarthEffect.java │ ├── EquationEffect.java │ ├── ExplodeEffect.java │ ├── FlameEffect.java │ ├── FountainEffect.java │ ├── GridEffect.java │ ├── HeartEffect.java │ ├── HelixEffect.java │ ├── HillEffect.java │ ├── IconEffect.java │ ├── ImageEffect.java │ ├── JumpEffect.java │ ├── LineEffect.java │ ├── LoveEffect.java │ ├── ModifiedEffect.java │ ├── MusicEffect.java │ ├── ParticleEffect.java │ ├── PlotEffect.java │ ├── PyramidEffect.java │ ├── ShieldEffect.java │ ├── SkyRocketEffect.java │ ├── SmokeEffect.java │ ├── SoundEffect.java │ ├── SphereEffect.java │ ├── StarEffect.java │ ├── TextEffect.java │ ├── TornadoEffect.java │ ├── TraceEffect.java │ ├── TurnEffect.java │ ├── VortexEffect.java │ ├── WarpEffect.java │ └── WaveEffect.java │ ├── math │ ├── ConstantTransform.java │ ├── EchoTransform.java │ ├── EquationStore.java │ ├── EquationTransform.java │ ├── MultiplyTransform.java │ ├── SequenceTransform.java │ ├── SumTransform.java │ ├── Transform.java │ ├── Transforms.java │ ├── VectorTransform.java │ ├── dQuadraticTransform.java │ └── dSinTransform.java │ └── util │ ├── BaseImageEffect.java │ ├── ConfigUtils.java │ ├── CustomSound.java │ ├── Disposable.java │ ├── DynamicLocation.java │ ├── ImageLoadCallback.java │ ├── ImageLoadTask.java │ ├── MathUtils.java │ ├── ParticleDisplay.java │ ├── ParticleEffect.java │ ├── RandomUtils.java │ ├── StringParser.java │ ├── VectorUtils.java │ └── versions │ ├── ParticleDisplay_12.java │ └── ParticleDisplay_13.java └── resources ├── migrate.php └── plugin.yml /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /.git/ 3 | /.settings/ 4 | /.classpath 5 | /.project 6 | target 7 | .idea 8 | *.iml 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | # 6.5 4 | 5 | - Add EffectManager.enableStackTraces to turn off stack traces in error messages 6 | - Add orient parameter to Circle effect 7 | 8 | # 6.4 9 | 10 | - Fix some issues with using lists of variables in equations getting out of order 11 | - Add Cuboid effect, can work with a source and target location (good for showing cuboid selections) 12 | - Add Pyramid effect 13 | - Add "Particle" effect for simple repeating particles 14 | - Add "Sound" effect for playing sounds or custom sounds, supporting volume and pitch-shifting 15 | - Add "probability" parameter for randomizing effects 16 | - Add "orient" parameter to Atom effect 17 | - Add "variableA" and "variableB" parameters to Modified effect 18 | - Add "particle_offset", shortcut for "particle_offset_x", y and z 19 | - Add "center" option to Grid effect 20 | 21 | # 6.3 22 | 23 | - Bleed effect now uses a "material" rather than "color" 24 | - Allow "forever" durations 25 | - All "random" colors 26 | 27 | # 6.2 28 | 29 | - Some specific internal FX fixes (please let me know if any effects look weird now) 30 | - Add "rotation" and "orient" parameters to image effects 31 | - Add parameters to TornadoEffect to reduce lag 32 | - Add orient parameter to Cylinder effect 33 | 34 | # 6.1 35 | 36 | - Fix redstone particles with no color specified (color is required for 1.13, defaults to red now) 37 | - Fix offset/relativeOffset used via API 38 | - Bring back legacy particle name lookup (Fixes MagicSpells compatibility) 39 | 40 | # 6.0 41 | 42 | - Plugins that interact directly with Effect properties may need to be rebuilt! Configuration-based plugins should be OK. 43 | - Added 1.13 Support 44 | - ParticleEffect has been deprecated, use the Spigot Particle API enum instead 45 | - EffectManager.display helper method available to handle colors, items and blocks in a version-independent way 46 | - Effect.materialData changed from Byte to byte 47 | 48 | # 5.9 49 | 50 | - Effects marked disappearWithOriginEntity or disappearWithTargetEntity will now disappear 51 | if their target goes invalid. 52 | - Allow underscore_style and dash_style parameters in configuration-based effects 53 | - Add EffectManager.registerEffectClass for registering short names for custom effects 54 | - Add "wholeCircle" option to Circle effect 55 | 56 | # 5.8 57 | 58 | - Add additional functions for use in equations: min, max, select 59 | - Min and max take two parameters and should be pretty self-explanatory. 60 | - The select function takes 4 parameters. 61 | - The first parameter is a test value, call it p0 62 | - The second parameter is returned if p0 < 0 63 | - The third parameter is returned if p0 == 0 64 | - The fourth parameter is returned if p0 > 0 65 | - Modified effect equations can now use a second parameter, "i", representing total # of iterations 66 | - Add x,y,z location equations to Modified effect, for moving the entire effect around. 67 | - Add Plot effect, mainly intended to be used for testing equations, not really for final effects 68 | - Fix particle offset x/y/z being an integer 69 | - ShieldEffect radius changed to floating point 70 | - Fix ImageEffect using a non-relative file path. 71 | 72 | # 5.7 73 | 74 | - Expanded EquationTransform support. 75 | - Added "transparency" option to ColoredImageEffect and ImageEffect 76 | - ImageEffect and ColoredImageEffect semi-merged, default particle for ImageEffect is now redstone 77 | - Optimize image effects, particularly with animations, to avoid constantly reloading the file 78 | - Image effects can now load files from a URL 79 | - Cache parsed equations for performance 80 | - Add ModifiedEffect, which allows you to parameterized any existing effect. 81 | 82 | # 5.6 83 | 84 | - Fix inconsistent position of Circle effect when using updateLocations: false 85 | 86 | # 5.5 87 | 88 | - Try to make Effect instances reusable (by calling start() again when they are finished) 89 | - Optimizations (thanks, XakepSDK!) 90 | - Fix builtin transforms, default package was wrong 91 | - Added setTargetPlayer API 92 | 93 | # 5.4 94 | 95 | - Memory use optimizations 96 | - Fix potential CME in EffectManager.cancel 97 | - Fix potential errors when playing FX while shutting down 98 | - Remove EntityManager. If you were using it, sorry, please open an Issue. 99 | 100 | # 5.3 101 | 102 | - Add direct yaw and pitch overrides to Effect 103 | 104 | # 5.2 105 | 106 | - Add support for 1.10 and 1.11 particles (FALLING_DUST, TOTEM, SPIT) 107 | 108 | # 5.1 109 | 110 | - Some updates to EquationEffect, may or may not change behavior (sorry!) 111 | - Fixes for the item_crack particle effect disconnecting clients 112 | 113 | ## 5.0 114 | 115 | - Add support for 1.10 116 | - Update to 1.9 sound names, now only fully compatible with 1.9 and up 117 | 118 | ## 4.3 119 | 120 | - Add cycle parameter to EquationEffect 121 | 122 | ## 4.2 123 | 124 | - Fix API, add back Effect.setLocation, setEntity, 125 | setTargetLocation, setTargetEntity 126 | - Add EquationEffect, for making custom effects using math equations 127 | 128 | ## 4.1 129 | 130 | - Add new particles from 1.9 131 | 132 | ## 4.0 133 | 134 | - 1.9 Compatibility 135 | - Add relativeOffset parameter (thanks, SexyToad!) 136 | - Dropped support for 1.7. It's no longer easy/possible to have backwards compatibility 137 | due to 1.9 dropping the old signature of getOnlinePlayers. 138 | 139 | ## 3.9 140 | 141 | - Add relativeOffset parameter (thanks, SexyToad!) 142 | - Dropped support for 1.7. It's no longer easy/possible to have backwards compatibility 143 | due to 1.9 dropping the old signature of getOnlinePlayers. 144 | 145 | ## 3.8 146 | 147 | - Add material and materialData parameters to all effects, for customizing 148 | block_crack and item_crack particle types 149 | - Add support for particle counts and offsets 150 | 151 | ## 3.7 152 | 153 | - Turn Effect.autoOrient off by default 154 | - Add updateLocations and updateDirections parameters, can be used to turn off Entity location tracking 155 | - Changed Cone and Vortex effects to better react to changes in direction 156 | - Fix BigBang (can't spawn Fireworks async!) 157 | - Config-driven effect classes may omit the "Effect" portion of the class name when using builtin effects 158 | - Effect "type" (instant, repeating, delayed) can now be set via configs 159 | 160 | ## 3.6 161 | 162 | - Fix LineEffect, broken in 3.5 163 | - Add "duration" parameter, a value in ms that can convert to period/iterations for you. 164 | 165 | ## 3.5 166 | 167 | - Add KCauldron support (Thank you, tpnils1!) 168 | - Add setParticleRange method to set default particle visibility range 169 | - Particles now use the "long range" flag when range is greater that 16 blocks 170 | - The old range of 256 seemed way too high, particles appear to vanish after 16 blocks if not long-range 171 | - Add generalized parameter support for Configuration-driven effects 172 | You can put variable names that start with "$" in the configuration, e.g. "$radius" 173 | Then when starting an effect, you can set $radius to a value in the parameterMap 174 | to automatically replace the variables in the config. 175 | - Add a DynamicLocation class to encapsulate an Entity or Location. 176 | This can be used to create a virtual entity, by controlling the location while the effect is runnning. 177 | 178 | ## 3.4 179 | 180 | - Effects now track an Entity relative to the given starting Location 181 | - Added some simpler versions of EffectManager.start() 182 | - Removed references to Apache Commons classes 183 | 184 | ## 3.0 185 | 186 | - Update particle names to match current ParticleEffect lib- please check code and configs! 187 | - Added colorizeable spell_mob, spell_mob_ambient and redstone particles 188 | - Full 1.8 support 189 | - Better error handling, config options for turning on/off log messages 190 | 191 | ## 2.1 192 | 193 | - Add MC 1.8 particle FX (will work even on Spigot protocol hack- avoid on Craftbukkit 1.7!) 194 | - Add displayTo methods for showing a particle to only one player. 195 | 196 | ## 2.0 197 | 198 | - Refactored Effect system. Most Effect class names have changed! 199 | - Combined Entity and Location Effects. 200 | 201 | ## 1.8 202 | 203 | - Last backward-compatible version of EffectLib. 204 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Slikey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EffectLib - Manage your effects the nice way. 2 | ========= 3 | 4 | # Note - Outdated! 5 | 6 | Development of this plugin/lib has been moved to http://github.com/elBukkit/EffectLib/ with much respect and appreciation to Slikey! 7 | 8 | This move was mainly done so the Maven group id could be changed to something that can be verified for submission to Maven central. 9 | 10 | # Introduction 11 | 12 | You have no idea what an vector or matrix is, but you want to give your users some nice effects with particles? No problem. this library comes with a load of effects for you. It handles rotation, text-parsing, and creation of 3D objects with particles in Minecraft. 13 | 14 | - Text-Parsing 15 | - 3D cubes, spheres, stars and others 16 | - 2D arcs, lines and many more! 17 | - Entity effects that enhance every game 18 | 19 | Find more information on [BukkitForums] [forum] or [BukkitDev] [dev]! 20 | 21 | Note that **this library** is no standalone plugin! You have to **create yourself a plugin** to run the effects! 22 | 23 | # How to Shade 24 | 25 | It is recommended to shade this plugin into yours. This way users of your plugin do not need to install EffectLib separately. 26 | 27 | This easy to do with Maven. First, add the elMakers repository: 28 | 29 | ``` 30 | 31 | 32 | github 33 | https://maven.pkg.github.com/Slikey/EffectLib 34 | 35 | 36 | 37 | elMakers 38 | http://maven.elmakers.com/repository/ 39 | 40 | 41 | ``` 42 | 43 | Then add the EffectLib dependency: 44 | 45 | ``` 46 | 47 | de.slikey 48 | EffectLib 49 | 6.3 50 | compile 51 | 52 | 53 | ``` 54 | 55 | Note the "compile" scope! 56 | 57 | Then finally add the Maven shade plugin: 58 | 59 | ``` 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-shade-plugin 64 | 3.0.0 65 | 66 | false 67 | ${project.build.directory}/dependency-reduced-pom.xml 68 | 69 | 70 | de.slikey 71 | com.your.own.package.slikey 72 | 73 | 74 | 75 | 76 | 77 | package 78 | 79 | shade 80 | 81 | 82 | 83 | 84 | 85 | ``` 86 | 87 | Make sure to change the "shadedPattern" to match the base package of your own plugin 88 | 89 | # Support 90 | 91 | Come visit the Magic Discord if you'd like EffectLib help: https://discord.gg/fWJ3W3kMjG 92 | 93 | # License 94 | 95 | MIT 96 | 97 | **Free Software, Hell Yeah!** 98 | 99 | [dev]:http://dev.bukkit.org/bukkit-plugins/effectlib/ 100 | [forum]:http://forums.bukkit.org/threads/effectlib-manage-your-effects-the-nice-way-text-in-particles.259879/ 101 | 102 | 103 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | * Player exclusion list, or player preference to disable effects 4 | * Async URL/File loading for image effects 5 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | de.slikey 5 | EffectLib 6 | 6.5-SNAPSHOT 7 | 8 | EffectLib 9 | http://www.kevin-carstens.de/ 10 | 11 | 12 | 13 | MIT License 14 | http://opensource.org/licenses/mit-license 15 | 16 | 17 | 18 | 19 | UTF-8 20 | 21 | 22 | 23 | scm:git:git://github.com/Slikey/EffectLib.git 24 | scm:git:git@github.com:Slikey/EffectLib.git 25 | https://github.com/Slikey/EffectLib/ 26 | master 27 | 28 | 29 | 30 | 31 | github 32 | EffectLib Apache Maven Packages 33 | https://maven.pkg.github.com/Slikey/EffectLib 34 | 35 | 36 | maven.elmakers.com 37 | https://maven.elmakers.com/repository/ 38 | 39 | 40 | 41 | 42 | 43 | spigot-repo 44 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 45 | 46 | 47 | 48 | 49 | 50 | org.bukkit 51 | bukkit 52 | 1.13-R0.1-SNAPSHOT 53 | 56 | provided 57 | 58 | 59 | net.objecthunter 60 | exp4j 61 | 0.4.5 62 | compile 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | src/main/resources/ 71 | true 72 | 73 | 74 | 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-compiler-plugin 79 | 3.3 80 | 81 | 1.6 82 | 1.6 83 | 84 | 85 | 86 | org.apache.maven.plugins 87 | maven-shade-plugin 88 | 1.5 89 | 90 | 91 | package 92 | 93 | shade 94 | 95 | 96 | 97 | 98 | net.objecthunter.exp4j 99 | de.slikey.exp4j 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/EffectLib.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib; 2 | 3 | import java.util.List; 4 | import org.bukkit.event.HandlerList; 5 | import org.bukkit.plugin.java.JavaPlugin; 6 | 7 | /*! \mainpage EffectLib Plugin API 8 | * 9 | * \section intro_sec Introduction 10 | * 11 | * This is the API for EffectLib, which gives developers access 12 | * to a wide variety of visual effects for use in their Plugins. 13 | * 14 | * \section issues_sec Issues 15 | * 16 | * For issues with the API, or suggestions, please use the devbukkit 17 | * project page: 18 | * 19 | * http://dev.bukkit.org/bukkit-plugins/effectlib/ 20 | * 21 | * \section start_sec Getting Started 22 | * 23 | * If you haven't done so already, get started with Bukkit by getting a basic 24 | * shell of a plugin working. You should at least have a working Plugin that 25 | * loads in Bukkit (add a debug print to onEnable to be sure!) before you 26 | * start trying to integrate with other Plugins. See here for general help: 27 | * 28 | * http://wiki.bukkit.org/Plugin_Tutorial 29 | * 30 | * \section maven_sec Building with Maven 31 | * 32 | * Once you have a project set up, it is easy to build against EffectLib 33 | * with Maven. Simply add the elmakers repository to your repository list, 34 | * and then add a dependency for EffectLib. A typical setup would look like: 35 | * 36 | *
 37 | * <dependencies>
 38 | * <dependency>
 39 | *     <groupId>org.bukkit</groupId>
 40 | *     <artifactId>bukkit</artifactId>
 41 | *     <version>1.6.4-R2.0</version>
 42 | *     <scope>provided</scope>
 43 | * </dependency>
 44 | * <dependency>
 45 | *     <groupId>de.slikey</groupId>
 46 | *     <artifactId>EffectLib</artifactId>
 47 | *     <version>1.4</version>
 48 | *     <scope>provided</scope>
 49 | * </dependency>
 50 | * </dependencies>
 51 | * <repositories>
 52 | * <repository>
 53 | *     <id>bukkit-repo</id>
 54 | *     <url>http://repo.bukkit.org/content/groups/public/ </url>
 55 | * </repository>
 56 | * <repository>
 57 | *     <id>elmakers-repo</id>
 58 | *     <url>http://maven.elmakers.com/repository/ </url>
 59 | * </repository>
 60 | * </repositories>
 61 | * 
62 | * 63 | * If you don't want to depend on EffectLib as an external library, you 64 | * can use the Maven shade plugin to "shade" the library into your own plugin. 65 | * This will relocate the library so you don't conflict with another instance 66 | * of it, even though all the EffectLib code is built in. Here is an example pom section: 67 | * 68 | *
 69 | * <plugin>
 70 | *     <groupId>org.apache.maven.plugins</groupId>
 71 | *     <artifactId>maven-shade-plugin</artifactId>
 72 | *     <version>1.5</version>
 73 | *     <executions>
 74 | *         <execution>
 75 | *             <phase>package</phase>
 76 | *             <goals>
 77 | *                 <goal>shade</goal>
 78 | *             </goals>
 79 | *             <configuration>
 80 | *                 <relocations>
 81 | *                     <relocation>
 82 | *                         <pattern>de.slikey</pattern>
 83 | *                         <shadedPattern>org.myplugin.slikey</shadedPattern>
 84 | *                     </relocation>
 85 | *                 </relocations>
 86 | *             </configuration>
 87 | *         </execution>
 88 | *     </executions>
 89 | * </plugin>
 90 | * 
91 | * 92 | * Once shaded, you can instantiate an EffectManager directly, passing it your Plugin 93 | * instance. 94 | * 95 | * \section plugin_sec Unshaded Usage 96 | * 97 | * 1. Get the instance of EffectLib first: 98 | * EffectLib lib = getEffectLib(); // See below 99 | * 2. Create a new EffectManager to handle your effects: 100 | * EffectManager em = new EffectManager(lib); 101 | * 3. Create a new Effect and add start it: 102 | * new BleedEntityEffect(em, player); 103 | * 4. Dispose the EffectManager after creating the last effect: 104 | * em.disposeOnTermination(); 105 | * 106 | * If you wish to softdepend to EffectLib, make sure to not use any of the effect classes 107 | * unless you know the EffectLib plugin is loaded. Make sure you're not building the Lib 108 | * into your plugin, it should always be referenced externally (e.g. "provided" in Maven). 109 | * 110 | *
111 | *       public EffectLib getEffectLib() {
112 | *           Plugin effectLib = Bukkit.getPluginManager().getPlugin("EffectLib");
113 | *             if (effectLib == null || !(effectLib instanceof EffectLib)) {
114 | *                 return null;
115 | *             }
116 | *           return (EffectLib)effectLib;
117 | *       }
118 | * 
119 | * 120 | */ 121 | public final class EffectLib extends JavaPlugin { 122 | 123 | private static EffectLib instance; 124 | 125 | public EffectLib() { 126 | instance = this; 127 | } 128 | 129 | @Override 130 | public void onEnable() { 131 | EffectManager.initialize(); 132 | } 133 | 134 | @Override 135 | public void onDisable() { 136 | EffectManager.disposeAll(); 137 | HandlerList.unregisterAll(this); 138 | } 139 | 140 | public List getEffectManagers() { 141 | return EffectManager.getManagers(); 142 | } 143 | 144 | public static EffectLib instance() { 145 | return instance; 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/EffectType.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib; 2 | 3 | public enum EffectType { 4 | 5 | /** 6 | * Effect is once played instantly. 7 | */ 8 | INSTANT, 9 | /** 10 | * Effect is several times played instantly. Set the interval with {@link Effect.period}. 11 | */ 12 | REPEATING, 13 | /** 14 | * Effect is once delayed played. Set delay with {@link Effect.delay}. 15 | */ 16 | DELAYED; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/AnimatedBallEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.VectorUtils; 9 | import org.bukkit.Location; 10 | import org.bukkit.util.Vector; 11 | 12 | /** 13 | * Creates an animated Sphere.. Thanks to the author for sharing it! 14 | * https://www.youtube.com/watch?feature=player_embedded&v=RUjIw_RprRw 15 | * 16 | * @author Qukie 17 | */ 18 | public class AnimatedBallEffect extends Effect { 19 | 20 | /** 21 | * ParticleType of spawned particle 22 | */ 23 | public Particle particle = Particle.SPELL_WITCH; 24 | 25 | /** 26 | * Ball particles total (150) 27 | */ 28 | public int particles = 150; 29 | 30 | /** 31 | * The amount of particles, displayed in one iteration (10) 32 | */ 33 | public int particlesPerIteration = 10; 34 | 35 | /** 36 | * Size of this ball (1) 37 | */ 38 | public float size = 1F; 39 | 40 | /** 41 | * Factors (1, 2, 1) 42 | */ 43 | public float xFactor = 1F, yFactor = 2F, zFactor = 1F; 44 | 45 | /** 46 | * Offsets (0, 0.8, 0) 47 | */ 48 | public float xOffset, yOffset = 0.8F, zOffset; 49 | 50 | /** 51 | * Rotation of the ball. 52 | */ 53 | public double xRotation, yRotation, zRotation = 0; 54 | 55 | /** 56 | * Internal Counter 57 | */ 58 | protected int step = 0; 59 | 60 | public AnimatedBallEffect(EffectManager effectManager) { 61 | super(effectManager); 62 | this.type = EffectType.REPEATING; 63 | this.iterations = 500; 64 | this.period = 1; 65 | } 66 | 67 | @Override 68 | public void reset() { 69 | this.step = 0; 70 | } 71 | 72 | @Override 73 | public void onRun() { 74 | Vector vector = new Vector(); 75 | Location location = getLocation(); 76 | for (int i = 0; i < particlesPerIteration; i++) { 77 | step++; 78 | 79 | float t = (MathUtils.PI / particles) * step; 80 | float r = MathUtils.sin(t) * size; 81 | float s = 2 * MathUtils.PI * t; 82 | 83 | vector.setX(xFactor * r * MathUtils.cos(s) + xOffset); 84 | vector.setZ(zFactor * r * MathUtils.sin(s) + zOffset); 85 | vector.setY(yFactor * size * MathUtils.cos(t) + yOffset); 86 | 87 | VectorUtils.rotateVector(vector, xRotation, yRotation, zRotation); 88 | 89 | display(particle, location.add(vector)); 90 | location.subtract(vector); 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/ArcEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import org.bukkit.Location; 8 | import org.bukkit.util.Vector; 9 | 10 | public class ArcEffect extends Effect { 11 | 12 | /** 13 | * ParticleType of spawned particle 14 | */ 15 | public Particle particle = Particle.FLAME; 16 | 17 | /** 18 | * Height of the arc in blocks 19 | */ 20 | public float height = 2; 21 | 22 | /** 23 | * Particles per arc 24 | */ 25 | public int particles = 100; 26 | 27 | /** 28 | * Internal counter 29 | */ 30 | protected int step = 0; 31 | 32 | public ArcEffect(EffectManager effectManager) { 33 | super(effectManager); 34 | type = EffectType.REPEATING; 35 | period = 1; 36 | iterations = 200; 37 | } 38 | 39 | @Override 40 | public void reset() { 41 | this.step = 0; 42 | } 43 | 44 | @Override 45 | public void onRun() { 46 | Location location = getLocation(); 47 | Location target = getTarget(); 48 | if (target == null) { 49 | cancel(); 50 | return; 51 | } 52 | Vector link = target.toVector().subtract(location.toVector()); 53 | float length = (float) link.length(); 54 | float pitch = (float) (4 * height / Math.pow(length, 2)); 55 | for (int i = 0; i < particles; i++) { 56 | Vector v = link.clone().normalize().multiply((float) length * i / particles); 57 | float x = ((float) i / particles) * length - length / 2; 58 | float y = (float) (-pitch * Math.pow(x, 2) + height); 59 | location.add(v).add(0, y, 0); 60 | display(particle, location); 61 | location.subtract(0, y, 0).subtract(v); 62 | 63 | step++; 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/AtomEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import de.slikey.effectlib.util.VectorUtils; 9 | import org.bukkit.Color; 10 | import org.bukkit.Location; 11 | import org.bukkit.util.Vector; 12 | 13 | public class AtomEffect extends Effect { 14 | 15 | /** 16 | * ParticleType of the nucleus 17 | */ 18 | public Particle particleNucleus = Particle.DRIP_WATER; 19 | public Color colorNucleus = null; 20 | 21 | /** 22 | * ParticleType of orbitals 23 | */ 24 | public Particle particleOrbital = Particle.DRIP_LAVA; 25 | public Color colorOrbital = null; 26 | 27 | /** 28 | * Radius of the atom 29 | */ 30 | public double radius = 3; 31 | 32 | /** 33 | * Radius of the nucleus as a fraction of the atom-radius 34 | */ 35 | public float radiusNucleus = .2f; 36 | 37 | /** 38 | * Particles to be spawned in the nucleus per iteration 39 | */ 40 | public int particlesNucleus = 10; 41 | 42 | /** 43 | * Particles to be spawned per orbital per iteration 44 | */ 45 | public int particlesOrbital = 10; 46 | 47 | /** 48 | * Orbitals around the nucleus 49 | */ 50 | public int orbitals = 3; 51 | 52 | /** 53 | * Rotation around the Y-axis 54 | */ 55 | public double rotation = 0; 56 | 57 | /** 58 | * Whether or not to orient to the direction of the source location 59 | */ 60 | public boolean orient = false; 61 | 62 | /** 63 | * Velocity of the orbitals 64 | */ 65 | public double angularVelocity = Math.PI / 80d; 66 | 67 | /** 68 | * Internal counter 69 | */ 70 | protected int step = 0; 71 | 72 | public AtomEffect(EffectManager effectManager) { 73 | super(effectManager); 74 | type = EffectType.REPEATING; 75 | period = 2; 76 | iterations = 200; 77 | } 78 | 79 | @Override 80 | public void reset() { 81 | this.step = 0; 82 | } 83 | 84 | @Override 85 | public void onRun() { 86 | Location location = getLocation(); 87 | for (int i = 0; i < particlesNucleus; i++) { 88 | Vector v = RandomUtils.getRandomVector().multiply(radius * radiusNucleus); 89 | if (orient) { 90 | v = VectorUtils.rotateVector(v, location); 91 | } 92 | location.add(v); 93 | display(particleNucleus, location, colorNucleus); 94 | location.subtract(v); 95 | } 96 | for (int i = 0; i < particlesOrbital; i++) { 97 | double angle = step * angularVelocity; 98 | for (int j = 0; j < orbitals; j++) { 99 | double xRotation = (Math.PI / orbitals) * j; 100 | Vector v = new Vector(Math.cos(angle), Math.sin(angle), 0).multiply(radius); 101 | VectorUtils.rotateAroundAxisX(v, xRotation); 102 | VectorUtils.rotateAroundAxisY(v, rotation); 103 | if (orient) { 104 | v = VectorUtils.rotateVector(v, location); 105 | } 106 | location.add(v); 107 | display(particleOrbital, location, colorOrbital); 108 | location.subtract(v); 109 | } 110 | step++; 111 | } 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/BigBangEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.RandomUtils; 7 | import org.bukkit.Color; 8 | import org.bukkit.FireworkEffect; 9 | import org.bukkit.FireworkEffect.Builder; 10 | import org.bukkit.Location; 11 | import org.bukkit.Sound; 12 | import org.bukkit.entity.EntityType; 13 | import org.bukkit.entity.Firework; 14 | import org.bukkit.inventory.meta.FireworkMeta; 15 | import org.bukkit.util.Vector; 16 | 17 | public class BigBangEffect extends Effect { 18 | 19 | public FireworkEffect.Type fireworkType = FireworkEffect.Type.BURST; 20 | public Color color2 = Color.ORANGE; 21 | public Color color3 = Color.BLACK; 22 | public Color fadeColor = Color.BLACK; 23 | public int intensity = 2; 24 | public float radius = 2; 25 | public int explosions = 10; 26 | public int soundInterval = 5; 27 | public Sound sound = Sound.ENTITY_GENERIC_EXPLODE; 28 | public float soundVolume = 100; 29 | public float soundPitch = 1; 30 | protected int step = 0; 31 | 32 | protected FireworkEffect firework; 33 | 34 | public BigBangEffect(EffectManager effectManager) { 35 | super(effectManager); 36 | color = Color.RED; 37 | type = EffectType.REPEATING; 38 | period = 2; 39 | iterations = 400; 40 | asynchronous = false; 41 | } 42 | 43 | @Override 44 | public void reset() { 45 | this.step = 0; 46 | } 47 | 48 | @Override 49 | public void onRun() { 50 | if (firework == null) { 51 | Builder b = FireworkEffect.builder().with(fireworkType); 52 | b.withColor(color).withColor(color2).withColor(color3); 53 | b.withFade(fadeColor); 54 | b.trail(true); 55 | firework = b.build(); 56 | } 57 | Location location = getLocation(); 58 | for (int i = 0; i < explosions; i++) { 59 | Vector v = RandomUtils.getRandomVector().multiply(radius); 60 | detonate(location, v); 61 | if (soundInterval != 0 && step % soundInterval == 0) { 62 | location.getWorld().playSound(location, sound, soundVolume, soundPitch); 63 | } 64 | } 65 | step++; 66 | } 67 | 68 | protected void detonate(Location location, Vector v) { 69 | final Firework fw = (Firework) location.getWorld().spawnEntity(location.add(v), EntityType.FIREWORK); 70 | location.subtract(v); 71 | FireworkMeta meta = fw.getFireworkMeta(); 72 | meta.setPower(0); 73 | for (int i = 0; i < intensity; i++) { 74 | meta.addEffect(firework); 75 | } 76 | fw.setFireworkMeta(meta); 77 | fw.detonate(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/BleedEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.EffectManager; 4 | import de.slikey.effectlib.EffectType; 5 | import de.slikey.effectlib.util.RandomUtils; 6 | import org.bukkit.Effect; 7 | import org.bukkit.Location; 8 | import org.bukkit.Material; 9 | import org.bukkit.entity.Entity; 10 | 11 | public class BleedEffect extends de.slikey.effectlib.Effect { 12 | 13 | /** 14 | * Play the Hurt Effect for the Player 15 | */ 16 | public boolean hurt = true; 17 | 18 | /** 19 | * Height of the blood spurt 20 | */ 21 | public double height = 1.75; 22 | 23 | /** 24 | * Color of blood. Default is red (152) 25 | */ 26 | public Material material = Material.REDSTONE_BLOCK; 27 | 28 | public BleedEffect(EffectManager effectManager) { 29 | super(effectManager); 30 | type = EffectType.REPEATING; 31 | period = 4; 32 | iterations = 25; 33 | } 34 | 35 | @Override 36 | public void onRun() { 37 | // Location to spawn the blood-item. 38 | Location location = getLocation(); 39 | location.add(0, RandomUtils.random.nextFloat() * height, 0); 40 | location.getWorld().playEffect(location, Effect.STEP_SOUND, material); 41 | 42 | Entity entity = getEntity(); 43 | if (hurt && entity != null) { 44 | entity.playEffect(org.bukkit.EntityEffect.HURT); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/CircleEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.VectorUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | public class CircleEffect extends Effect { 12 | 13 | /** 14 | * Whether or not to orient to the direction of the source location 15 | */ 16 | public boolean orient = false; 17 | 18 | /* 19 | * ParticleType of spawned particle 20 | */ 21 | public Particle particle = Particle.VILLAGER_HAPPY; 22 | 23 | /* 24 | * Rotation of the torus. 25 | */ 26 | public double xRotation, yRotation, zRotation = 0; 27 | 28 | /* 29 | * Turns the cube by this angle each iteration around the x-axis 30 | */ 31 | public double angularVelocityX = Math.PI / 200; 32 | 33 | /* 34 | * Turns the cube by this angle each iteration around the y-axis 35 | */ 36 | public double angularVelocityY = Math.PI / 170; 37 | 38 | /* 39 | * Turns the cube by this angle each iteration around the z-axis 40 | */ 41 | public double angularVelocityZ = Math.PI / 155; 42 | 43 | /* 44 | * Radius of circle above head 45 | */ 46 | public float radius = .4f; 47 | 48 | /* 49 | * Current step. Works as a counter 50 | */ 51 | protected float step = 0; 52 | 53 | /* 54 | * Subtracts from location if needed 55 | */ 56 | public double xSubtract, ySubtract, zSubtract; 57 | 58 | /* 59 | * Should it rotate? 60 | */ 61 | public boolean enableRotation = true; 62 | 63 | /* 64 | * Amount of particles per circle 65 | */ 66 | public int particles = 20; 67 | 68 | /** 69 | * To make a whole circle each iteration 70 | */ 71 | public boolean wholeCircle = false; 72 | 73 | public CircleEffect(EffectManager effectManager) { 74 | super(effectManager); 75 | type = EffectType.REPEATING; 76 | period = 2; 77 | iterations = 50; 78 | } 79 | 80 | @Override 81 | public void reset() { 82 | this.step = 0; 83 | } 84 | 85 | @Override 86 | public void onRun() { 87 | Location location = getLocation(); 88 | location.subtract(xSubtract, ySubtract, zSubtract); 89 | double inc = (2 * Math.PI) / particles; 90 | int steps = wholeCircle ? particles : 1; 91 | for (int i = 0; i < steps; i++) { 92 | double angle = step * inc; 93 | Vector v = new Vector(); 94 | v.setX(Math.cos(angle) * radius); 95 | v.setZ(Math.sin(angle) * radius); 96 | VectorUtils.rotateVector(v, xRotation, yRotation, zRotation); 97 | if (enableRotation) { 98 | VectorUtils.rotateVector(v, angularVelocityX * step, angularVelocityY * step, angularVelocityZ * step); 99 | } 100 | if (orient) { 101 | v = VectorUtils.rotateVector(v, location); 102 | } 103 | display(particle, location.clone().add(v), 0, 30); 104 | step++; 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/CloudEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import org.bukkit.Color; 9 | import org.bukkit.Location; 10 | import org.bukkit.util.Vector; 11 | 12 | public class CloudEffect extends Effect { 13 | 14 | /* 15 | * Particle of the cloud 16 | */ 17 | public Particle cloudParticle = Particle.CLOUD; 18 | public Color cloudColor = null; 19 | 20 | /* 21 | * Particle of the rain/snow 22 | */ 23 | public Particle mainParticle = Particle.DRIP_WATER; 24 | 25 | /* 26 | * Size of the cloud 27 | */ 28 | public float cloudSize = .7f; 29 | 30 | /* 31 | * Radius of the rain/snow 32 | */ 33 | public float particleRadius = cloudSize - .1f; 34 | 35 | /* 36 | * Y-Offset from location 37 | */ 38 | public double yOffset = .8; 39 | 40 | public CloudEffect(EffectManager manager) { 41 | super(manager); 42 | type = EffectType.REPEATING; 43 | period = 5; 44 | iterations = 50; 45 | } 46 | 47 | @Override 48 | public void onRun() { 49 | Location location = getLocation(); 50 | location.add(0, yOffset, 0); 51 | for (int i = 0; i < 50; i++) { 52 | Vector v = RandomUtils.getRandomCircleVector().multiply(RandomUtils.random.nextDouble() * cloudSize); 53 | display(cloudParticle, location.add(v), cloudColor, 0, 7); 54 | location.subtract(v); 55 | } 56 | Location l = location.add(0, .2, 0); 57 | for (int i = 0; i < 15; i++) { 58 | int r = RandomUtils.random.nextInt(2); 59 | double x = RandomUtils.random.nextDouble() * particleRadius; 60 | double z = RandomUtils.random.nextDouble() * particleRadius; 61 | l.add(x, 0, z); 62 | if (r != 1) { 63 | display(mainParticle, l); 64 | } 65 | l.subtract(x, 0, z); 66 | l.subtract(x, 0, z); 67 | if (r != 1) { 68 | display(mainParticle, l); 69 | } 70 | l.add(x, 0, z); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/ColoredImageEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.EffectManager; 4 | import de.slikey.effectlib.util.BaseImageEffect; 5 | import org.bukkit.Location; 6 | import org.bukkit.util.Vector; 7 | 8 | import java.awt.Color; 9 | import java.awt.image.BufferedImage; 10 | 11 | public class ColoredImageEffect extends BaseImageEffect { 12 | public ColoredImageEffect(EffectManager effectManager) { 13 | super(effectManager); 14 | } 15 | 16 | protected void display(BufferedImage image, Vector v, Location location, int pixel) { 17 | Color color = new Color(pixel); 18 | int r = color.getRed(); 19 | int g = color.getGreen(); 20 | int b = color.getBlue(); 21 | display(particle, location.add(v), org.bukkit.Color.fromRGB(r, g, b)); 22 | location.subtract(v); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/ConeEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.RandomUtils; 9 | import de.slikey.effectlib.util.VectorUtils; 10 | import org.bukkit.Location; 11 | import org.bukkit.util.Vector; 12 | 13 | public class ConeEffect extends Effect { 14 | 15 | /** 16 | * ParticleType of spawned particle 17 | */ 18 | public Particle particle = Particle.FLAME; 19 | 20 | /** 21 | * Growing per iteration in the length (0.05) 22 | */ 23 | public float lengthGrow = .05f; 24 | 25 | /** 26 | * Radials per iteration to spawn the next particle (PI / 16) 27 | */ 28 | public double angularVelocity = Math.PI / 16; 29 | 30 | /** 31 | * Cone-particles per interation (10) 32 | */ 33 | public int particles = 10; 34 | 35 | /** 36 | * Growth in blocks per iteration on the radius (0.006) 37 | */ 38 | public float radiusGrow = 0.006f; 39 | 40 | /** 41 | * Conesize in particles per cone 42 | */ 43 | public int particlesCone = 180; 44 | 45 | /** 46 | * Start-angle or rotation of the cone 47 | */ 48 | public double rotation = 0; 49 | 50 | /** 51 | * Randomize every cone on creation (false) 52 | */ 53 | public boolean randomize = false; 54 | 55 | /** 56 | * Current step. Works as counter 57 | */ 58 | protected int step = 0; 59 | 60 | public ConeEffect(EffectManager effectManager) { 61 | super(effectManager); 62 | type = EffectType.REPEATING; 63 | period = 1; 64 | iterations = 200; 65 | } 66 | 67 | @Override 68 | public void reset() { 69 | this.step = 0; 70 | } 71 | 72 | @Override 73 | public void onRun() { 74 | Location location = getLocation(); 75 | for (int x = 0; x < particles; x++) { 76 | if (step > particlesCone) { 77 | step = 0; 78 | } 79 | if (randomize && step == 0) { 80 | rotation = RandomUtils.getRandomAngle(); 81 | } 82 | double angle = step * angularVelocity + rotation; 83 | float radius = step * radiusGrow; 84 | float length = step * lengthGrow; 85 | Vector v = new Vector(Math.cos(angle) * radius, length, Math.sin(angle) * radius); 86 | VectorUtils.rotateAroundAxisX(v, (location.getPitch() + 90) * MathUtils.degreesToRadians); 87 | VectorUtils.rotateAroundAxisY(v, -location.getYaw() * MathUtils.degreesToRadians); 88 | 89 | location.add(v); 90 | display(particle, location); 91 | location.subtract(v); 92 | step++; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/CubeEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.VectorUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | public class CubeEffect extends Effect { 12 | 13 | /** 14 | * Particle of the cube 15 | */ 16 | public Particle particle = Particle.FLAME; 17 | 18 | /** 19 | * Length of the edges 20 | */ 21 | public float edgeLength = 3; 22 | 23 | /** 24 | * Turns the cube by this angle each iteration around the x-axis 25 | */ 26 | public double angularVelocityX = Math.PI / 200; 27 | 28 | /** 29 | * Turns the cube by this angle each iteration around the y-axis 30 | */ 31 | public double angularVelocityY = Math.PI / 170; 32 | 33 | /** 34 | * Turns the cube by this angle each iteration around the z-axis 35 | */ 36 | public double angularVelocityZ = Math.PI / 155; 37 | 38 | /** 39 | * Particles in each row 40 | */ 41 | public int particles = 8; 42 | 43 | /** 44 | * True if rotation is enable 45 | */ 46 | public boolean enableRotation = true; 47 | 48 | /** 49 | * Only the outlines are drawn 50 | */ 51 | public boolean outlineOnly = true; 52 | 53 | /** 54 | * Current step. Works as counter 55 | */ 56 | protected int step = 0; 57 | 58 | public CubeEffect(EffectManager effectManager) { 59 | super(effectManager); 60 | type = EffectType.REPEATING; 61 | period = 5; 62 | iterations = 200; 63 | } 64 | 65 | @Override 66 | public void reset() { 67 | this.step = 0; 68 | } 69 | 70 | @Override 71 | public void onRun() { 72 | Location location = getLocation(); 73 | if (outlineOnly) { 74 | drawCubeOutline(location); 75 | } else { 76 | drawCubeWalls(location); 77 | } 78 | step++; 79 | } 80 | 81 | private void drawCubeOutline(Location location) { 82 | double xRotation = 0, yRotation = 0, zRotation = 0; 83 | if (enableRotation) { 84 | xRotation = step * angularVelocityX; 85 | yRotation = step * angularVelocityY; 86 | zRotation = step * angularVelocityZ; 87 | } 88 | float a = edgeLength / 2; 89 | // top and bottom 90 | double angleX, angleY; 91 | Vector v = new Vector(); 92 | for (int i = 0; i < 4; i++) { 93 | angleY = i * Math.PI / 2; 94 | for (int j = 0; j < 2; j++) { 95 | angleX = j * Math.PI; 96 | for (int p = 0; p <= particles; p++) { 97 | v.setX(a).setY(a); 98 | v.setZ(edgeLength * p / particles - a); 99 | VectorUtils.rotateAroundAxisX(v, angleX); 100 | VectorUtils.rotateAroundAxisY(v, angleY); 101 | 102 | if (enableRotation) { 103 | VectorUtils.rotateVector(v, xRotation, yRotation, zRotation); 104 | } 105 | display(particle, location.add(v)); 106 | location.subtract(v); 107 | } 108 | } 109 | // pillars 110 | for (int p = 0; p <= particles; p++) { 111 | v.setX(a).setZ(a); 112 | v.setY(edgeLength * p / particles - a); 113 | VectorUtils.rotateAroundAxisY(v, angleY); 114 | 115 | if (enableRotation) { 116 | VectorUtils.rotateVector(v, xRotation, yRotation, zRotation); 117 | } 118 | display(particle, location.add(v)); 119 | location.subtract(v); 120 | } 121 | } 122 | } 123 | 124 | private void drawCubeWalls(Location location) { 125 | double xRotation = 0, yRotation = 0, zRotation = 0; 126 | if (enableRotation) { 127 | xRotation = step * angularVelocityX; 128 | yRotation = step * angularVelocityY; 129 | zRotation = step * angularVelocityZ; 130 | } 131 | float a = edgeLength / 2; 132 | for (int x = 0; x <= particles; x++) { 133 | float posX = edgeLength * ((float) x / particles) - a; 134 | for (int y = 0; y <= particles; y++) { 135 | float posY = edgeLength * ((float) y / particles) - a; 136 | for (int z = 0; z <= particles; z++) { 137 | if (x != 0 && x != particles && y != 0 && y != particles && z != 0 && z != particles) { 138 | continue; 139 | } 140 | float posZ = edgeLength * ((float) z / particles) - a; 141 | Vector v = new Vector(posX, posY, posZ); 142 | if (enableRotation) { 143 | VectorUtils.rotateVector(v, xRotation, yRotation, zRotation); 144 | } 145 | display(particle, location.add(v)); 146 | location.subtract(v); 147 | } 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/CuboidEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.Particle; 5 | import org.bukkit.util.Vector; 6 | 7 | import de.slikey.effectlib.Effect; 8 | import de.slikey.effectlib.EffectManager; 9 | import de.slikey.effectlib.EffectType; 10 | 11 | public class CuboidEffect extends Effect { 12 | 13 | /** 14 | * Particle of the cube 15 | */ 16 | public Particle particle = Particle.FLAME; 17 | 18 | /** 19 | * Particles in each row 20 | */ 21 | public int particles = 8; 22 | 23 | /** 24 | * Length of x component of cuboid 25 | */ 26 | public double xLength = 0; 27 | 28 | /** 29 | * Length of y component of cuboid 30 | */ 31 | public double yLength = 0; 32 | 33 | /** 34 | * Length of z component of cuboid 35 | */ 36 | public double zLength = 0; 37 | 38 | /** 39 | * Amount of padding to add around the cube 40 | */ 41 | public double padding = 0; 42 | 43 | /** 44 | * Use corners of blocks 45 | */ 46 | public boolean blockSnap = false; 47 | 48 | /** 49 | * State variables 50 | */ 51 | protected Location minCorner; 52 | protected boolean initialized; 53 | 54 | public CuboidEffect(EffectManager effectManager) { 55 | super(effectManager); 56 | type = EffectType.REPEATING; 57 | period = 5; 58 | iterations = 200; 59 | } 60 | 61 | @Override 62 | public void onRun() { 63 | Location target = getTarget(); 64 | Location location = getLocation(); 65 | if (!initialized) { 66 | if (blockSnap) { 67 | target = target.getBlock().getLocation(); 68 | minCorner = location.getBlock().getLocation(); 69 | } else { 70 | minCorner = location.clone(); 71 | } 72 | if (xLength == 0 && yLength == 0 && zLength == 0) { 73 | if (target == null || !target.getWorld().equals(location.getWorld())) { 74 | cancel(); 75 | return; 76 | } 77 | if (target.getX() < minCorner.getX()) { 78 | minCorner.setX(target.getX()); 79 | } 80 | if (target.getY() < minCorner.getY()) { 81 | minCorner.setY(target.getY()); 82 | } 83 | if (target.getZ() < minCorner.getZ()) { 84 | minCorner.setZ(target.getZ()); 85 | } 86 | if (padding != 0) { 87 | minCorner.add(-padding, -padding, -padding); 88 | } 89 | double extra = padding * 2; 90 | if (blockSnap) extra++; 91 | xLength = Math.abs(location.getX() - target.getX()) + extra; 92 | yLength = Math.abs(location.getY() - target.getY()) + extra; 93 | zLength = Math.abs(location.getZ() - target.getZ()) + extra; 94 | } 95 | initialized = true; 96 | } 97 | drawOutline(location, target); 98 | } 99 | 100 | private void drawOutline(Location location, Location target) { 101 | Vector v = new Vector(); 102 | for (int i = 0; i < particles; i++) { 103 | // X edges 104 | drawEdge(v, i, 0, 2, 2); 105 | drawEdge(v, i, 0, 1, 2); 106 | drawEdge(v, i, 0, 1, 1); 107 | drawEdge(v, i, 0, 2, 1); 108 | 109 | // Y edges 110 | drawEdge(v, i, 2, 0, 2); 111 | drawEdge(v, i, 1,0, 2); 112 | drawEdge(v, i, 1,0, 1); 113 | drawEdge(v, i, 2,0, 1); 114 | 115 | // Z edges 116 | drawEdge(v, i, 2, 2, 0); 117 | drawEdge(v, i, 1, 2, 0); 118 | drawEdge(v, i, 1, 1, 0); 119 | drawEdge(v, i, 2, 1, 0); 120 | } 121 | } 122 | 123 | private void drawEdge(Vector v, int i, int dx, int dy, int dz) { 124 | if (dx == 0) { 125 | v.setX(xLength * i / particles); 126 | } else { 127 | v.setX(xLength * (dx - 1)); 128 | } 129 | if (dy == 0) { 130 | v.setY(yLength * i / particles); 131 | } else { 132 | v.setY(yLength * (dy - 1)); 133 | } 134 | if (dz == 0) { 135 | v.setZ(zLength * i / particles); 136 | } else { 137 | v.setZ(zLength * (dz - 1)); 138 | } 139 | display(particle, minCorner.add(v)); 140 | minCorner.subtract(v); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/CylinderEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.RandomUtils; 9 | import de.slikey.effectlib.util.VectorUtils; 10 | import java.util.Random; 11 | import org.bukkit.Location; 12 | import org.bukkit.util.Vector; 13 | 14 | public class CylinderEffect extends Effect { 15 | 16 | /** 17 | * Particle of the cube 18 | */ 19 | public Particle particle = Particle.FLAME; 20 | 21 | /** 22 | * Radius of cylinder 23 | */ 24 | public float radius = 1; 25 | 26 | /** 27 | * Height of Cylinder 28 | */ 29 | public float height = 3; 30 | 31 | /** 32 | * Turns the cube by this angle each iteration around the x-axis 33 | */ 34 | public double angularVelocityX = Math.PI / 200; 35 | 36 | /** 37 | * Turns the cube by this angle each iteration around the y-axis 38 | */ 39 | public double angularVelocityY = Math.PI / 170; 40 | 41 | /** 42 | * Turns the cube by this angle each iteration around the z-axis 43 | */ 44 | public double angularVelocityZ = Math.PI / 155; 45 | 46 | /** 47 | * Rotation of the cylinder 48 | */ 49 | public double rotationX, rotationY, rotationZ; 50 | 51 | /** 52 | * Particles in each row 53 | */ 54 | public int particles = 100; 55 | 56 | /** 57 | * True if rotation is enable 58 | */ 59 | public boolean enableRotation = true; 60 | 61 | /** 62 | * Toggles the cylinder to be solid 63 | */ 64 | public boolean solid = false; 65 | 66 | /** 67 | * Current step. Works as counter 68 | */ 69 | protected int step = 0; 70 | 71 | /** 72 | * Ratio of sides to entire surface 73 | */ 74 | protected float sideRatio = 0; 75 | 76 | /** 77 | * Whether or not to orient the effect in the direction 78 | * of the source Location 79 | */ 80 | public boolean orient = false; 81 | 82 | public CylinderEffect(EffectManager effectManager) { 83 | super(effectManager); 84 | type = EffectType.REPEATING; 85 | period = 2; 86 | iterations = 200; 87 | } 88 | 89 | @Override 90 | public void reset() { 91 | this.step = 0; 92 | } 93 | 94 | @Override 95 | public void onRun() { 96 | Location location = getLocation(); 97 | if (sideRatio == 0) { 98 | calculateSideRatio(); 99 | } 100 | Random r = RandomUtils.random; 101 | double xRotation = rotationX, yRotation = rotationY, zRotation = rotationZ; 102 | if (orient) { 103 | xRotation = Math.toRadians(90 - location.getPitch()) + rotationX; 104 | yRotation = Math.toRadians(180 - location.getYaw()) + rotationY; 105 | } 106 | if (enableRotation) { 107 | xRotation += step * angularVelocityX; 108 | yRotation += step * angularVelocityY; 109 | zRotation += step * angularVelocityZ; 110 | } 111 | for (int i = 0; i < particles; i++) { 112 | float multi = (solid) ? r.nextFloat() : 1; 113 | Vector v = RandomUtils.getRandomCircleVector().multiply(radius); 114 | if (r.nextFloat() <= sideRatio) { 115 | // SIDE PARTICLE 116 | v.multiply(multi); 117 | v.setY((r.nextFloat() * 2 - 1) * (height / 2)); 118 | } else { 119 | // GROUND PARTICLE 120 | v.multiply(r.nextFloat()); 121 | if (r.nextFloat() < 0.5) { 122 | // TOP 123 | v.setY(multi * (height / 2)); 124 | } else { 125 | // BOTTOM 126 | v.setY(-multi * (height / 2)); 127 | } 128 | } 129 | if (enableRotation || orient) { 130 | VectorUtils.rotateVector(v, xRotation, yRotation, zRotation); 131 | } 132 | display(particle, location.add(v)); 133 | location.subtract(v); 134 | } 135 | display(particle, location); 136 | step++; 137 | } 138 | 139 | protected void calculateSideRatio() { 140 | float grounds, side; 141 | grounds = MathUtils.PI * MathUtils.PI * radius * 2; 142 | side = 2 * MathUtils.PI * radius * height; 143 | sideRatio = side / (side + grounds); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/DiscoBallEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | /* 4 | * Idea by coco5843 5 | */ 6 | import de.slikey.effectlib.Effect; 7 | import de.slikey.effectlib.EffectManager; 8 | import de.slikey.effectlib.EffectType; 9 | import org.bukkit.Particle; 10 | import de.slikey.effectlib.util.RandomUtils; 11 | import org.bukkit.Color; 12 | import org.bukkit.Location; 13 | import org.bukkit.util.Vector; 14 | 15 | public class DiscoBallEffect extends Effect { 16 | 17 | /** 18 | * Radius of the sphere 19 | */ 20 | public float sphereRadius = .6f; 21 | 22 | /** 23 | * Min and max sizes of the lines 24 | */ 25 | public int max = 15; 26 | 27 | /** 28 | * Particle of the sphere and of the lines 29 | */ 30 | public Particle sphereParticle = Particle.FLAME, lineParticle = Particle.REDSTONE; 31 | public Color sphereColor = null, lineColor = null; 32 | 33 | /** 34 | * Max number of lines 35 | */ 36 | public int maxLines = 7; 37 | 38 | /** 39 | * Max number of particles per line 40 | */ 41 | public int lineParticles = 100, sphereParticles = 50; 42 | 43 | /** 44 | * Direction of the lines 45 | */ 46 | public Direction direction = Direction.DOWN; 47 | 48 | public DiscoBallEffect(EffectManager manager) { 49 | super(manager); 50 | type = EffectType.REPEATING; 51 | period = 7; 52 | iterations = 500; 53 | } 54 | 55 | public void onRun() { 56 | Location location = getLocation(); 57 | //Lines 58 | int mL = RandomUtils.random.nextInt(maxLines - 2) + 2; 59 | for (int m = 0; m < mL * 2; m++) { 60 | double x = RandomUtils.random.nextInt(max - max * (-1)) + max * (-1); 61 | double y = RandomUtils.random.nextInt(max - max * (-1)) + max * (-1); 62 | double z = RandomUtils.random.nextInt(max - max * (-1)) + max * (-1); 63 | if (direction == Direction.DOWN) { 64 | y = RandomUtils.random.nextInt(max * 2 - max) + max; 65 | } else if (direction == Direction.UP) { 66 | y = RandomUtils.random.nextInt(max * (-1) - max * (-2)) + max * (-2); 67 | } 68 | Location target = location.clone().subtract(x, y, z); 69 | if (target == null) { 70 | cancel(); 71 | return; 72 | } 73 | Vector link = target.toVector().subtract(location.toVector()); 74 | float length = (float) link.length(); 75 | link.normalize(); 76 | 77 | float ratio = length / lineParticles; 78 | Vector v = link.multiply(ratio); 79 | Location loc = location.clone().subtract(v); 80 | for (int i = 0; i < lineParticles; i++) { 81 | loc.add(v); 82 | display(lineParticle, loc, lineColor); 83 | } 84 | } 85 | 86 | //Sphere 87 | for (int i = 0; i < sphereParticles; i++) { 88 | Vector vector = RandomUtils.getRandomVector().multiply(sphereRadius); 89 | location.add(vector); 90 | display(sphereParticle, location, sphereColor); 91 | location.subtract(vector); 92 | } 93 | } 94 | 95 | public enum Direction { 96 | 97 | UP, DOWN, BOTH; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/DnaEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.VectorUtils; 9 | import org.bukkit.Color; 10 | import org.bukkit.Location; 11 | import org.bukkit.util.Vector; 12 | 13 | public class DnaEffect extends Effect { 14 | 15 | /** 16 | * ParticleType of spawned particle 17 | */ 18 | public Particle particleHelix = Particle.FLAME; 19 | public Color colorHelix = null; 20 | 21 | /** 22 | * Particle of base 1 23 | */ 24 | public Particle particleBase1 = Particle.WATER_WAKE; 25 | public Color colorBase1 = null; 26 | 27 | /** 28 | * Particle of base 2 29 | */ 30 | public Particle particleBase2 = Particle.REDSTONE; 31 | public Color colorBase2 = null; 32 | 33 | /** 34 | * Radials to turn per step 35 | */ 36 | public double radials = Math.PI / 30; 37 | 38 | /** 39 | * Radius of dna-double-helix 40 | */ 41 | public float radius = 1.5f; 42 | 43 | /** 44 | * Particles to spawn per interation 45 | */ 46 | public int particlesHelix = 3; 47 | 48 | /** 49 | * Particles per base 50 | */ 51 | public int particlesBase = 15; 52 | 53 | /** 54 | * Length of the dna-double-helix 55 | */ 56 | public float length = 15; 57 | 58 | /** 59 | * Growth per particle 60 | */ 61 | public float grow = 0.2f; 62 | 63 | /** 64 | * Particles between every base 65 | */ 66 | public float baseInterval = 10; 67 | 68 | /** 69 | * Current step. Works as counter 70 | */ 71 | protected int step = 0; 72 | 73 | public DnaEffect(EffectManager effectManager) { 74 | super(effectManager); 75 | type = EffectType.REPEATING; 76 | period = 1; 77 | iterations = 500; 78 | } 79 | 80 | @Override 81 | public void reset() { 82 | this.step = 0; 83 | } 84 | 85 | @Override 86 | public void onRun() { 87 | Location location = getLocation(); 88 | for (int j = 0; j < particlesHelix; j++) { 89 | if (step * grow > length) { 90 | step = 0; 91 | } 92 | for (int i = 0; i < 2; i++) { 93 | double angle = step * radials + Math.PI * i; 94 | Vector v = new Vector(Math.cos(angle) * radius, step * grow, Math.sin(angle) * radius); 95 | drawParticle(location, v, particleHelix, colorHelix); 96 | } 97 | if (step % baseInterval == 0) { 98 | for (int i = -particlesBase; i <= particlesBase; i++) { 99 | if (i == 0) { 100 | continue; 101 | } 102 | Particle particle = particleBase1; 103 | Color color = colorBase1; 104 | if (i < 0) { 105 | particle = particleBase2; 106 | color = colorBase2; 107 | } 108 | double angle = step * radials; 109 | Vector v = new Vector(Math.cos(angle), 0, Math.sin(angle)).multiply(radius * i / particlesBase).setY(step * grow); 110 | drawParticle(location, v, particle, color); 111 | } 112 | } 113 | step++; 114 | } 115 | } 116 | 117 | protected void drawParticle(Location location, Vector v, Particle particle, Color color) { 118 | VectorUtils.rotateAroundAxisX(v, (location.getPitch() + 90) * MathUtils.degreesToRadians); 119 | VectorUtils.rotateAroundAxisY(v, -location.getYaw() * MathUtils.degreesToRadians); 120 | 121 | location.add(v); 122 | display(particle, location, color); 123 | location.subtract(v); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/DonutEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.VectorUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | public class DonutEffect extends Effect { 12 | 13 | /** 14 | * ParticleType of spawned particle 15 | */ 16 | public Particle particle = Particle.FLAME; 17 | 18 | /** 19 | * Amount of particles inside of a single vertical circle 20 | */ 21 | public int particlesCircle = 10; 22 | 23 | /** 24 | * Amount of circles to build the torus 25 | */ 26 | public int circles = 36; 27 | 28 | /** 29 | * Radius of the torus 30 | */ 31 | public float radiusDonut = 2; 32 | 33 | /** 34 | * Radius of the tube (the circles on the outside. 35 | */ 36 | public float radiusTube = .5f; 37 | 38 | /** 39 | * Rotation of the torus. 40 | */ 41 | public double xRotation, yRotation, zRotation = 0; 42 | 43 | public DonutEffect(EffectManager effectManager) { 44 | super(effectManager); 45 | type = EffectType.REPEATING; 46 | period = 10; 47 | iterations = 20; 48 | } 49 | 50 | @Override 51 | public void onRun() { 52 | Location location = getLocation(); 53 | Vector v = new Vector(); 54 | for (int i = 0; i < circles; i++) { 55 | double theta = 2 * Math.PI * i / circles; 56 | for (int j = 0; j < particlesCircle; j++) { 57 | double phi = 2 * Math.PI * j / particlesCircle; 58 | double cosPhi = Math.cos(phi); 59 | v.setX((radiusDonut + radiusTube * cosPhi) * Math.cos(theta)); 60 | v.setY((radiusDonut + radiusTube * cosPhi) * Math.sin(theta)); 61 | v.setZ(radiusTube * Math.sin(phi)); 62 | 63 | VectorUtils.rotateVector(v, xRotation, yRotation, zRotation); 64 | 65 | display(particle, location.add(v)); 66 | location.subtract(v); 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/DragonEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.RandomUtils; 9 | import de.slikey.effectlib.util.VectorUtils; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import org.bukkit.Location; 13 | import org.bukkit.util.Vector; 14 | 15 | public class DragonEffect extends Effect { 16 | 17 | protected final List rndF; 18 | protected final List rndAngle; 19 | /** 20 | * ParticleType of spawned particle 21 | */ 22 | public Particle particle = Particle.FLAME; 23 | /** 24 | * Pitch of the dragon arc 25 | */ 26 | public float pitch = .1f; 27 | /** 28 | * Arcs to build the breath 29 | */ 30 | public int arcs = 20; 31 | /** 32 | * Particles per arc 33 | */ 34 | public int particles = 30; 35 | /** 36 | * Steps per iteration 37 | */ 38 | public int stepsPerIteration = 2; 39 | /** 40 | * Length in blocks 41 | */ 42 | public float length = 4; 43 | /** 44 | * Current step. Works as counter 45 | */ 46 | protected int step = 0; 47 | 48 | public DragonEffect(EffectManager effectManager) { 49 | super(effectManager); 50 | type = EffectType.REPEATING; 51 | period = 2; 52 | iterations = 200; 53 | rndF = new ArrayList(arcs); 54 | rndAngle = new ArrayList(arcs); 55 | } 56 | 57 | @Override 58 | public void reset() { 59 | this.step = 0; 60 | } 61 | 62 | @Override 63 | public void onRun() { 64 | Location location = getLocation(); 65 | for (int j = 0; j < stepsPerIteration; j++) { 66 | if (step % particles == 0) { 67 | rndF.clear(); 68 | rndAngle.clear(); 69 | } 70 | while (rndF.size() < arcs) { 71 | rndF.add(RandomUtils.random.nextFloat()); 72 | } 73 | while (rndAngle.size() < arcs) { 74 | rndAngle.add(RandomUtils.getRandomAngle()); 75 | } 76 | for (int i = 0; i < arcs; i++) { 77 | float pitch = rndF.get(i) * 2 * this.pitch - this.pitch; 78 | float x = (step % particles) * length / particles; 79 | float y = (float) (pitch * Math.pow(x, 2)); 80 | Vector v = new Vector(x, y, 0); 81 | VectorUtils.rotateAroundAxisX(v, rndAngle.get(i)); 82 | VectorUtils.rotateAroundAxisZ(v, -location.getPitch() * MathUtils.degreesToRadians); 83 | VectorUtils.rotateAroundAxisY(v, -(location.getYaw() + 90) * MathUtils.degreesToRadians); 84 | display(particle, location.add(v)); 85 | location.subtract(v); 86 | } 87 | step++; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/EarthEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.RandomUtils; 9 | import de.slikey.effectlib.util.VectorUtils; 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | import org.bukkit.Location; 13 | import org.bukkit.util.Vector; 14 | 15 | public class EarthEffect extends Effect { 16 | public Particle particle1 = Particle.VILLAGER_HAPPY; 17 | public Particle particle2 = Particle.DRIP_WATER; 18 | 19 | /** 20 | * Precision of generation. Higher numbers have better results, but increase the time of generation. Don't pick Number above 10.000 21 | */ 22 | public int precision = 100; 23 | 24 | /** 25 | * Amount of Particles to form the World 26 | */ 27 | public int particles = 500; 28 | 29 | /** 30 | * Radius of the World 31 | */ 32 | public float radius = 1; 33 | 34 | /** 35 | * Height of the mountains. 36 | */ 37 | public float mountainHeight = .5f; 38 | 39 | /** 40 | * Triggers invalidation on first run 41 | */ 42 | protected boolean firstStep = true; 43 | 44 | /** 45 | * Caches vectors to increase performance 46 | */ 47 | protected final Set cacheGreen, cacheBlue; 48 | 49 | public EarthEffect(EffectManager effectManager) { 50 | super(effectManager); 51 | type = EffectType.REPEATING; 52 | period = 5; 53 | iterations = 200; 54 | cacheGreen = new HashSet(); 55 | cacheBlue = new HashSet(); 56 | } 57 | 58 | @Override 59 | public void reset() { 60 | this.firstStep = true; 61 | } 62 | 63 | public void invalidate() { 64 | firstStep = false; 65 | cacheGreen.clear(); 66 | cacheBlue.clear(); 67 | 68 | Set cache = new HashSet(); 69 | int sqrtParticles = (int) Math.sqrt(particles); 70 | float theta = 0, phi, thetaStep = MathUtils.PI / sqrtParticles, phiStep = MathUtils.PI2 / sqrtParticles; 71 | for (int i = 0; i < sqrtParticles; i++) { 72 | theta += thetaStep; 73 | phi = 0; 74 | for (int j = 0; j < sqrtParticles; j++) { 75 | phi += phiStep; 76 | float x = radius * MathUtils.sin(theta) * MathUtils.cos(phi); 77 | float y = radius * MathUtils.sin(theta) * MathUtils.sin(phi); 78 | float z = radius * MathUtils.cos(theta); 79 | cache.add(new Vector(x, y, z)); 80 | } 81 | } 82 | 83 | float increase = mountainHeight / precision; 84 | for (int i = 0; i < precision; i++) { 85 | double r1 = RandomUtils.getRandomAngle(), r2 = RandomUtils.getRandomAngle(), r3 = RandomUtils.getRandomAngle(); 86 | for (Vector v : cache) { 87 | if (v.getY() > 0) { 88 | v.setY(v.getY() + increase); 89 | } else { 90 | v.setY(v.getY() - increase); 91 | } 92 | if (i != precision - 1) { 93 | VectorUtils.rotateVector(v, r1, r2, r3); 94 | } 95 | } 96 | } 97 | 98 | float minSquared = Float.POSITIVE_INFINITY, maxSquared = Float.NEGATIVE_INFINITY; 99 | for (Vector current : cache) { 100 | float lengthSquared = (float) current.lengthSquared(); 101 | if (minSquared > lengthSquared) { 102 | minSquared = lengthSquared; 103 | } 104 | if (maxSquared < lengthSquared) { 105 | maxSquared = lengthSquared; 106 | } 107 | } 108 | 109 | // COLOR PARTICLES 110 | float average = (minSquared + maxSquared) / 2; 111 | for (Vector v : cache) { 112 | float lengthSquared = (float) v.lengthSquared(); 113 | if (lengthSquared >= average) { 114 | cacheGreen.add(v); 115 | } else { 116 | cacheBlue.add(v); 117 | } 118 | } 119 | } 120 | 121 | @Override 122 | public void onRun() { 123 | Location location = getLocation(); 124 | if (firstStep) { 125 | invalidate(); 126 | } 127 | for (Vector v : cacheGreen) { 128 | display(particle1, location.add(v), 0, 3); 129 | location.subtract(v); 130 | } 131 | for (Vector v : cacheBlue) { 132 | display(particle2, location.add(v)); 133 | location.subtract(v); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/EquationEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.math.EquationStore; 7 | import de.slikey.effectlib.math.EquationTransform; 8 | import org.bukkit.Particle; 9 | import de.slikey.effectlib.util.VectorUtils; 10 | import org.bukkit.Location; 11 | import org.bukkit.util.Vector; 12 | 13 | public class EquationEffect extends Effect { 14 | 15 | /** 16 | * ParticleType of spawned particle 17 | */ 18 | public Particle particle = Particle.REDSTONE; 19 | 20 | /** 21 | * Equations defining the X,Y,Z coordinates over 22 | * iteration t 23 | * 24 | * These equations can make use of most common math functions, 25 | * including randomized numbers. Some examples: 26 | * 27 | * 4*sin(t) 28 | * cos(t * rand(-4,5) + 32 29 | * tan(t) 30 | */ 31 | public String xEquation = "t"; 32 | public String yEquation = "0"; 33 | public String zEquation = "0"; 34 | 35 | /** 36 | * The variable name used in equations to represent major ticks 37 | */ 38 | public String variable = "t"; 39 | 40 | /** 41 | * How many steps to take per iteration 42 | */ 43 | public int particles = 1; 44 | 45 | /** 46 | * A set of equations that, if set, will be performed in a sub-iteration 47 | * for each major iteration. 48 | */ 49 | public String x2Equation = null; 50 | public String y2Equation = null; 51 | public String z2Equation = null; 52 | 53 | /** 54 | * The variable name used in sub-equations to represent minor ticks 55 | */ 56 | public String variable2 = "t2"; 57 | 58 | /** 59 | * How many steps to take per sub-iteration 60 | */ 61 | public int particles2 = 0; 62 | 63 | /** 64 | * Whether or not to orient the effect in the direction 65 | * of the source Location 66 | * 67 | * If this is set to true, the X axis will represent "forward". 68 | */ 69 | public boolean orient = true; 70 | 71 | /** 72 | * Similar to orient, however this is specific to pitch. 73 | */ 74 | public boolean orientPitch = true; 75 | 76 | /** 77 | * These is the limit for the steps until it starts over. 78 | */ 79 | public int maxSteps = 0; 80 | 81 | /** 82 | * If this is true, after cycling the inner equation, it'll be set to 0. 83 | * Set this to false if you want the miniStep to be saved between major steps. 84 | */ 85 | public boolean cycleMiniStep = true; 86 | 87 | private EquationTransform xTransform; 88 | private EquationTransform yTransform; 89 | private EquationTransform zTransform; 90 | 91 | private EquationTransform x2Transform; 92 | private EquationTransform y2Transform; 93 | private EquationTransform z2Transform; 94 | 95 | private int step = 0; 96 | private int miniStep = 0; 97 | 98 | public EquationEffect(EffectManager effectManager) { 99 | super(effectManager); 100 | type = EffectType.REPEATING; 101 | period = 1; 102 | iterations = 100; 103 | } 104 | 105 | @Override 106 | public void reset() { 107 | this.step = 0; 108 | this.miniStep = 0; 109 | } 110 | 111 | @Override 112 | public void onRun() { 113 | if (xTransform == null) { 114 | xTransform = EquationStore.getInstance().getTransform(xEquation, variable); 115 | yTransform = EquationStore.getInstance().getTransform(yEquation, variable); 116 | zTransform = EquationStore.getInstance().getTransform(zEquation, variable); 117 | 118 | if (x2Equation != null && y2Equation != null && z2Equation != null && particles2 > 0) { 119 | x2Transform = EquationStore.getInstance().getTransform(x2Equation, variable, variable2); 120 | y2Transform = EquationStore.getInstance().getTransform(y2Equation, variable, variable2); 121 | z2Transform = EquationStore.getInstance().getTransform(z2Equation, variable, variable2); 122 | } 123 | } 124 | Location location = getLocation(); 125 | 126 | boolean hasInnerEquation = (x2Transform != null && y2Transform != null && z2Transform != null); 127 | for (int i = 0; i < particles; i++) { 128 | Double xValue = xTransform.get(step); 129 | Double yValue = yTransform.get(step); 130 | Double zValue = zTransform.get(step); 131 | 132 | Vector result = new Vector(xValue, yValue, zValue); 133 | if (orient && orientPitch) { 134 | result = VectorUtils.rotateVector(result, location); 135 | } else if (orient) { 136 | result = VectorUtils.rotateVector(result, location.getYaw(), 0); 137 | } 138 | 139 | Location targetLocation = location.clone(); 140 | targetLocation.add(result); 141 | if (!hasInnerEquation) { 142 | display(particle, targetLocation); 143 | } else { 144 | for (int j = 0; j < particles2; j++) { 145 | Double x2Value = x2Transform.get(step, miniStep); 146 | Double y2Value = y2Transform.get(step, miniStep); 147 | Double z2Value = z2Transform.get(step, miniStep); 148 | 149 | Vector result2 = new Vector(x2Value, y2Value, z2Value); 150 | if (orient && orientPitch) { 151 | result2 = VectorUtils.rotateVector(result2, location); 152 | } else if (orient) { 153 | result2 = VectorUtils.rotateVector(result2, location.getYaw(), 0); 154 | } 155 | 156 | Location target2Location = targetLocation.clone().add(result2); 157 | display(particle, target2Location); 158 | 159 | miniStep++; 160 | } 161 | 162 | if (cycleMiniStep) { 163 | miniStep = 0; 164 | } 165 | } 166 | if (maxSteps != 0 && step > maxSteps) { 167 | step = 0; 168 | break; 169 | } else { 170 | step++; 171 | } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/ExplodeEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.Sound; 10 | 11 | public class ExplodeEffect extends Effect { 12 | public Particle particle1 = Particle.EXPLOSION_NORMAL; 13 | public Particle particle2 = Particle.EXPLOSION_HUGE; 14 | 15 | /** 16 | * Amount of spawned smoke-sparks 17 | */ 18 | public int amount = 25; 19 | public Sound sound = Sound.ENTITY_GENERIC_EXPLODE; 20 | 21 | public ExplodeEffect(EffectManager effectManager) { 22 | super(effectManager); 23 | type = EffectType.INSTANT; 24 | speed = 0.5f; 25 | } 26 | 27 | @Override 28 | public void onRun() { 29 | Location location = getLocation(); 30 | location.getWorld().playSound(location, sound, 4.0F, (1.0F + (RandomUtils.random.nextFloat() - RandomUtils.random.nextFloat()) * 0.2F) * 0.7F); 31 | display(particle1, location); 32 | display(particle2, location); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/FlameEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | public class FlameEffect extends Effect { 12 | 13 | public Particle particle = Particle.FLAME; 14 | 15 | public FlameEffect(EffectManager effectManager) { 16 | super(effectManager); 17 | type = EffectType.REPEATING; 18 | period = 1; 19 | iterations = 600; 20 | } 21 | 22 | @Override 23 | public void onRun() { 24 | Location location = getLocation(); 25 | for (int i = 0; i < 10; i++) { 26 | Vector v = RandomUtils.getRandomCircleVector().multiply(RandomUtils.random.nextDouble() * 0.6d); 27 | v.setY(RandomUtils.random.nextFloat() * 1.8); 28 | location.add(v); 29 | display(particle, location); 30 | location.subtract(v); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/FountainEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | public class FountainEffect extends Effect { 12 | 13 | /** 14 | * Particle of the fountain 15 | */ 16 | public Particle particle = Particle.WATER_SPLASH; 17 | 18 | /** 19 | * Amount of strands (10) 20 | */ 21 | public int strands = 10; 22 | 23 | /** 24 | * Particles per iteration per strand (100) 25 | */ 26 | public int particlesStrand = 150; 27 | 28 | /** 29 | * Particles per iteration in the spout 30 | */ 31 | public int particlesSpout = 200; 32 | 33 | /** 34 | * Radius of strands in blocks 35 | */ 36 | public float radius = 5; 37 | 38 | /** 39 | * Radius of spout as a fraction of the fountain (0.1) 40 | */ 41 | public float radiusSpout = .1f; 42 | 43 | /** 44 | * Height of the fountain 45 | */ 46 | public float height = 3; 47 | 48 | /** 49 | * Height of the spout in blocks 50 | */ 51 | public float heightSpout = 7; 52 | 53 | /** 54 | * Rotation of the fountain on the Y-Axis (Fraction of PI) 55 | */ 56 | public double rotation = Math.PI / 4; 57 | 58 | public FountainEffect(EffectManager effectManager) { 59 | super(effectManager); 60 | type = EffectType.REPEATING; 61 | period = 2; 62 | iterations = 100; 63 | } 64 | 65 | @Override 66 | public void onRun() { 67 | Location location = getLocation(); 68 | for (int i = 1; i <= strands; i++) { 69 | double angle = 2 * i * Math.PI / strands + rotation; 70 | for (int j = 1; j <= particlesStrand; j++) { 71 | float ratio = (float) j / particlesStrand; 72 | double x, y, z; 73 | x = Math.cos(angle) * radius * ratio; 74 | y = Math.sin(Math.PI * j / particlesStrand) * height; 75 | z = Math.sin(angle) * radius * ratio; 76 | location.add(x, y, z); 77 | display(particle, location); 78 | location.subtract(x, y, z); 79 | } 80 | } 81 | for (int i = 0; i < particlesSpout; i++) { 82 | Vector v = RandomUtils.getRandomCircleVector().multiply(RandomUtils.random.nextFloat() * radius * radiusSpout); 83 | v.setY(RandomUtils.random.nextFloat() * heightSpout); 84 | location.add(v); 85 | display(particle, location); 86 | location.subtract(v); 87 | } 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/GridEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.VectorUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | public class GridEffect extends Effect { 12 | 13 | /** 14 | * ParticleType of the nucleus 15 | */ 16 | public Particle particle = Particle.FLAME; 17 | 18 | /** 19 | * Rows of the grid 20 | */ 21 | public int rows = 5; 22 | 23 | /** 24 | * Columns of the grid 25 | */ 26 | public int columns = 10; 27 | 28 | /** 29 | * Width per cell in blocks 30 | */ 31 | public float widthCell = 1; 32 | 33 | /** 34 | * Height per cell in blocks 35 | */ 36 | public float heightCell = 1; 37 | 38 | /** 39 | * Particles to be spawned on the horizontal borders of the cell 40 | */ 41 | public int particlesWidth = 4; 42 | 43 | /** 44 | * Particles to be spawned on the vertical borders of the cell 45 | */ 46 | public int particlesHeight = 3; 47 | 48 | /** 49 | * Rotation around the Y-axis 50 | */ 51 | public double rotation = 0; 52 | 53 | /** 54 | * Rotation around the X-axis 55 | */ 56 | public double rotationX = 0; 57 | 58 | /** 59 | * Rotation around the Z-axis 60 | */ 61 | public double rotationZ = 0; 62 | 63 | /** 64 | * To center the grid on the location 65 | */ 66 | public boolean center = false; 67 | 68 | public GridEffect(EffectManager effectManager) { 69 | super(effectManager); 70 | type = EffectType.INSTANT; 71 | period = 5; 72 | iterations = 50; 73 | } 74 | 75 | @Override 76 | public void onRun() { 77 | Location location = getLocation(); 78 | Vector v = new Vector(); 79 | // Draw rows 80 | for (int i = 0; i <= (rows + 1); i++) { 81 | for (int j = 0; j < particlesWidth * (columns + 1); j++) { 82 | v.setY(i * heightCell); 83 | v.setX(j * widthCell / particlesWidth); 84 | addParticle(location, v); 85 | } 86 | } 87 | // Draw columns 88 | for (int i = 0; i <= (columns + 1); i++) { 89 | for (int j = 0; j < particlesHeight * (rows + 1); j++) { 90 | v.setX(i * widthCell); 91 | v.setY(j * heightCell / particlesHeight); 92 | addParticle(location, v); 93 | } 94 | } 95 | } 96 | 97 | protected void addParticle(Location location, Vector v) { 98 | v.setZ(0); 99 | if (center) { 100 | v.setY(v.getY() + heightCell * -(rows + 1) / 2); 101 | v.setX(v.getX() + widthCell * -(columns + 1) / 2); 102 | } 103 | VectorUtils.rotateAroundAxisY(v, rotation); 104 | if (rotationX != 0) { 105 | VectorUtils.rotateAroundAxisX(v, rotationX); 106 | } 107 | if (rotationZ != 0) { 108 | VectorUtils.rotateAroundAxisZ(v, rotationZ); 109 | } 110 | location.add(v); 111 | display(particle, location); 112 | location.subtract(v); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/HeartEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.util.MathUtils; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.VectorUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | /** 12 | * Creates a 2D Heart in 3D space. Thanks to the author for sharing it! 13 | * 14 | * @author Qukie 15 | */ 16 | public class HeartEffect extends Effect { 17 | 18 | /** 19 | * ParticleType of spawned particle 20 | */ 21 | public Particle particle = Particle.CRIT_MAGIC; 22 | 23 | /** 24 | * Heart-particles per interation (100) 25 | */ 26 | public int particles = 50; 27 | 28 | /** 29 | * Rotation of the heart. 30 | */ 31 | public double xRotation, yRotation, zRotation = 0; 32 | 33 | /** 34 | * Stretch/Compress factor along the x or y axis (1, 1) 35 | */ 36 | public double yFactor = 1, xFactor = 1; 37 | 38 | /** 39 | * Defines the size of the that inner sting (0.8) \/ 40 | */ 41 | public double factorInnerSpike = 0.8; 42 | 43 | /** 44 | * Compresses the heart along the y axis. (2) 45 | */ 46 | public double compressYFactorTotal = 2; 47 | 48 | /** 49 | * Compilation of the heart. (2) 50 | */ 51 | public float compilaction = 2F; 52 | 53 | public HeartEffect(EffectManager effectManager) { 54 | super(effectManager); 55 | } 56 | 57 | @Override 58 | public void onRun() { 59 | Location location = getLocation(); 60 | Vector vector = new Vector(); 61 | for (int i = 0; i < particles; i++) { 62 | float alpha = ((MathUtils.PI / compilaction) / particles) * i; 63 | double phi = Math.pow(Math.abs(MathUtils.sin(2 * compilaction * alpha)) + factorInnerSpike * Math.abs(MathUtils.sin(compilaction * alpha)), 1 / compressYFactorTotal); 64 | 65 | vector.setY(phi * (MathUtils.sin(alpha) + MathUtils.cos(alpha)) * yFactor); 66 | vector.setZ(phi * (MathUtils.cos(alpha) - MathUtils.sin(alpha)) * xFactor); 67 | 68 | VectorUtils.rotateVector(vector, xRotation, yRotation, zRotation); 69 | 70 | display(particle, location.add(vector)); 71 | location.subtract(vector); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/HelixEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import org.bukkit.Location; 8 | 9 | public class HelixEffect extends Effect { 10 | 11 | /** 12 | * Particle to form the helix 13 | */ 14 | public Particle particle = Particle.FLAME; 15 | 16 | /** 17 | * Amount of strands 18 | */ 19 | public int strands = 8; 20 | 21 | /** 22 | * Particles per strand 23 | */ 24 | public int particles = 80; 25 | 26 | /** 27 | * Radius of helix 28 | */ 29 | public float radius = 10; 30 | 31 | /** 32 | * Factor for the curves. Negative values reverse rotation. 33 | */ 34 | public float curve = 10; 35 | 36 | /** 37 | * Rotation of the helix (Fraction of PI) 38 | */ 39 | public double rotation = Math.PI / 4; 40 | 41 | public HelixEffect(EffectManager effectManager) { 42 | super(effectManager); 43 | type = EffectType.REPEATING; 44 | period = 10; 45 | iterations = 8; 46 | } 47 | 48 | @Override 49 | public void onRun() { 50 | Location location = getLocation(); 51 | for (int i = 1; i <= strands; i++) { 52 | for (int j = 1; j <= particles; j++) { 53 | float ratio = (float) j / particles; 54 | double angle = curve * ratio * 2 * Math.PI / strands + (2 * Math.PI * i / strands) + rotation; 55 | double x = Math.cos(angle) * ratio * radius; 56 | double z = Math.sin(angle) * ratio * radius; 57 | location.add(x, 0, z); 58 | display(particle, location); 59 | location.subtract(x, 0, z); 60 | } 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/HillEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.VectorUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | /** 12 | * Taken from http://en.wikipedia.org/wiki/Torus 13 | * 14 | * @author Kevin 15 | */ 16 | public class HillEffect extends Effect { 17 | 18 | /** 19 | * ParticleType of spawned particle 20 | */ 21 | public Particle particle = Particle.FLAME; 22 | 23 | /** 24 | * Height of the hill in blocks 25 | */ 26 | public float height = 2.5f; 27 | 28 | /** 29 | * Amount of particles per row 30 | */ 31 | public float particles = 30; 32 | 33 | /** 34 | * Length of the edge 35 | */ 36 | public float edgeLength = 6.5f; 37 | 38 | /** 39 | * Rotation of the Hill 40 | */ 41 | public double yRotation = Math.PI / 7; 42 | 43 | public HillEffect(EffectManager effectManager) { 44 | super(effectManager); 45 | type = EffectType.REPEATING; 46 | period = 10; 47 | iterations = 20; 48 | } 49 | 50 | @Override 51 | public void onRun() { 52 | Location location = getLocation(); 53 | Vector v = new Vector(); 54 | for (int x = 0; x <= particles; x++) { 55 | double y1 = Math.sin(Math.PI * x / particles); 56 | for (int z = 0; z <= particles; z++) { 57 | double y2 = Math.sin(Math.PI * z / particles); 58 | v.setX(edgeLength * x / particles).setZ(edgeLength * z / particles); 59 | v.setY(height * y1 * y2); 60 | VectorUtils.rotateAroundAxisY(v, yRotation); 61 | 62 | display(particle, location.add(v)); 63 | location.subtract(v); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/IconEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import org.bukkit.Location; 8 | 9 | public class IconEffect extends Effect { 10 | 11 | /** 12 | * ParticleType of spawned particle 13 | */ 14 | public Particle particle = Particle.VILLAGER_ANGRY; 15 | 16 | public int yOffset = 2; 17 | 18 | public IconEffect(EffectManager effectManager) { 19 | super(effectManager); 20 | type = EffectType.REPEATING; 21 | period = 4; 22 | iterations = 25; 23 | } 24 | 25 | @Override 26 | public void onRun() { 27 | Location location = getLocation(); 28 | location.add(0, yOffset, 0); 29 | display(particle, location); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/ImageEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.EffectManager; 4 | import de.slikey.effectlib.util.BaseImageEffect; 5 | import de.slikey.effectlib.util.MathUtils; 6 | import de.slikey.effectlib.util.VectorUtils; 7 | import org.bukkit.Location; 8 | import org.bukkit.util.Vector; 9 | 10 | import java.awt.Color; 11 | import java.awt.image.BufferedImage; 12 | 13 | public class ImageEffect extends BaseImageEffect { 14 | 15 | /** 16 | * Invert the image 17 | */ 18 | public boolean invert = false; 19 | 20 | public ImageEffect(EffectManager effectManager) { 21 | super(effectManager); 22 | } 23 | 24 | protected void display(BufferedImage image, Vector v, Location location, int pixel) { 25 | if (!invert && Color.black.getRGB() != pixel) { 26 | return; 27 | } else if (invert && Color.black.getRGB() == pixel) { 28 | return; 29 | } 30 | display(particle, location.add(v)); 31 | location.subtract(v); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/JumpEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.entity.Entity; 7 | import org.bukkit.util.Vector; 8 | 9 | public class JumpEffect extends Effect { 10 | 11 | /** 12 | * Power of jump. (0.5f) 13 | */ 14 | public float power = .5f; 15 | 16 | public JumpEffect(EffectManager effectManager) { 17 | super(effectManager); 18 | type = EffectType.INSTANT; 19 | period = 20; 20 | iterations = 1; 21 | asynchronous = false; 22 | } 23 | 24 | @Override 25 | public void onRun() { 26 | Entity entity = getEntity(); 27 | if (entity == null) { 28 | cancel(); 29 | return; 30 | } 31 | Vector v = entity.getVelocity(); 32 | v.setY(v.getY() + power); 33 | entity.setVelocity(v); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/LineEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import org.bukkit.Location; 8 | import org.bukkit.util.Vector; 9 | 10 | public class LineEffect extends Effect { 11 | 12 | /** 13 | * ParticleType of spawned particle 14 | */ 15 | public Particle particle = Particle.FLAME; 16 | 17 | /** 18 | * Should it do a zig zag? 19 | */ 20 | public boolean isZigZag = false; 21 | 22 | /** 23 | * Number of zig zags in the line 24 | */ 25 | public int zigZags = 10; 26 | 27 | /** 28 | * Direction of zig-zags 29 | */ 30 | public Vector zigZagOffset = new Vector(0,0.1,0); 31 | 32 | /** 33 | * Particles per arc 34 | */ 35 | public int particles = 100; 36 | 37 | /** 38 | * Length of arc 39 | * A non-zero value here will use a length instead of the target endpoint 40 | */ 41 | public double length = 0; 42 | 43 | /** 44 | * Internal boolean 45 | */ 46 | protected boolean zag = false; 47 | 48 | /** 49 | * Internal counter 50 | */ 51 | protected int step = 0; 52 | 53 | public LineEffect(EffectManager effectManager) { 54 | super(effectManager); 55 | type = EffectType.REPEATING; 56 | period = 1; 57 | iterations = 1; 58 | } 59 | 60 | @Override 61 | public void reset() { 62 | this.step = 0; 63 | } 64 | 65 | @Override 66 | public void onRun() { 67 | Location location = getLocation(); 68 | Location target = null; 69 | if (length > 0) { 70 | target = location.clone().add(location.getDirection().normalize().multiply(length)); 71 | } else { 72 | target = getTarget(); 73 | } 74 | int amount = particles / zigZags; 75 | if (target == null) { 76 | cancel(); 77 | return; 78 | } 79 | Vector link = target.toVector().subtract(location.toVector()); 80 | float length = (float) link.length(); 81 | link.normalize(); 82 | 83 | float ratio = length / particles; 84 | Vector v = link.multiply(ratio); 85 | Location loc = location.clone().subtract(v); 86 | for (int i = 0; i < particles; i++) { 87 | if (isZigZag) { 88 | if (zag) { 89 | loc.add(zigZagOffset); 90 | } else { 91 | loc.subtract(zigZagOffset); 92 | } 93 | } 94 | if (step >= amount) { 95 | if (zag) { 96 | zag = false; 97 | } else { 98 | zag = true; 99 | } 100 | step = 0; 101 | } 102 | step++; 103 | loc.add(v); 104 | display(particle, loc); 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/LoveEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import org.bukkit.Location; 9 | 10 | public class LoveEffect extends Effect { 11 | 12 | /** 13 | * Particle to display 14 | */ 15 | public Particle particle = Particle.HEART; 16 | 17 | public LoveEffect(EffectManager effectManager) { 18 | super(effectManager); 19 | type = EffectType.REPEATING; 20 | period = 2; 21 | iterations = 600; 22 | } 23 | 24 | @Override 25 | public void onRun() { 26 | Location location = getLocation(); 27 | location.add(RandomUtils.getRandomCircleVector().multiply(RandomUtils.random.nextDouble() * 0.6d)); 28 | location.add(0, RandomUtils.random.nextFloat() * 2, 0); 29 | display(particle, location); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/ModifiedEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.Arrays; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import org.bukkit.Location; 10 | import org.bukkit.configuration.ConfigurationSection; 11 | import org.bukkit.util.Vector; 12 | 13 | import com.google.common.base.CaseFormat; 14 | 15 | import de.slikey.effectlib.Effect; 16 | import de.slikey.effectlib.EffectManager; 17 | import de.slikey.effectlib.EffectType; 18 | import de.slikey.effectlib.math.EquationStore; 19 | import de.slikey.effectlib.math.EquationTransform; 20 | import de.slikey.effectlib.util.VectorUtils; 21 | 22 | public class ModifiedEffect extends Effect { 23 | private final static String[] _variables = {"t", "i", "a", "b"}; 24 | private final static List variables = Arrays.asList(_variables); 25 | 26 | /** 27 | * The base configuration of the inner effect. 28 | */ 29 | public ConfigurationSection effect; 30 | 31 | /** 32 | * The class name of the effect to modify. 33 | * 34 | * Can be left blank if class is set in effect configuration. 35 | */ 36 | public String effectClass; 37 | 38 | /** 39 | * Move the entire effect's x location around 40 | */ 41 | public String xEquation = null; 42 | 43 | /** 44 | * Move the entire effect's y location around 45 | */ 46 | public String yEquation = null; 47 | 48 | /** 49 | * Move the entire effect's z location around 50 | */ 51 | public String zEquation = null; 52 | 53 | /** 54 | * The starting value of variable a 55 | */ 56 | public double variableA; 57 | 58 | /** 59 | * The starting value of variable b 60 | */ 61 | public double variableB; 62 | 63 | /** 64 | * Whether or not to orient the effect in the direction 65 | * of the source Location 66 | * 67 | * If this is set to true, the X axis will represent "forward". 68 | * 69 | * This is only used if setting an x, y, z equation. 70 | */ 71 | public boolean orient = true; 72 | 73 | /** 74 | * Similar to orient, however this is specific to pitch. 75 | */ 76 | public boolean orientPitch = false; 77 | 78 | /** 79 | * Effect parameters to modify each tick, paired with an equation used to modify them. 80 | */ 81 | public Map parameters = new HashMap(); 82 | 83 | private boolean initialized = false; 84 | private Effect innerEffect; 85 | private Map parameterTransforms = new HashMap(); 86 | private int step = 0; 87 | 88 | private EquationTransform xTransform; 89 | private EquationTransform yTransform; 90 | private EquationTransform zTransform; 91 | private Vector previousOffset; 92 | 93 | public ModifiedEffect(EffectManager effectManager) { 94 | super(effectManager); 95 | type = EffectType.REPEATING; 96 | period = 1; 97 | iterations = 100; 98 | } 99 | 100 | @Override 101 | public void reset() { 102 | this.step = 0; 103 | if (innerEffect != null) { 104 | innerEffect.prepare(); 105 | } 106 | } 107 | 108 | @Override 109 | public void onDone() { 110 | if (innerEffect != null) { 111 | innerEffect.onDone(); 112 | } 113 | } 114 | 115 | @Override 116 | public void onRun() { 117 | if (!initialized) { 118 | initialized = true; 119 | if (effect == null) { 120 | effectManager.onError("ModifiedEffect missing inner effect configuration"); 121 | cancel(); 122 | return; 123 | } 124 | 125 | if (effectClass == null) { 126 | effectClass = effect.getString("class"); 127 | } 128 | if (effectClass == null) { 129 | effectManager.onError("ModifiedEffect missing inner effect class property"); 130 | cancel(); 131 | return; 132 | } 133 | 134 | innerEffect = effectManager.getEffect(effectClass, effect, origin, target, null, targetPlayer); 135 | if (innerEffect == null) { 136 | cancel(); 137 | return; 138 | } 139 | innerEffect.material = material; 140 | innerEffect.materialData = materialData; 141 | for (Map.Entry entry : parameters.entrySet()) { 142 | String equation = entry.getValue(); 143 | String fieldName = entry.getKey(); 144 | 145 | // Allow underscore_style and dash_style parameters 146 | if (fieldName.contains("-")) { 147 | fieldName = fieldName.replace("-", "_"); 148 | } 149 | if (fieldName.contains("_")) { 150 | fieldName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, fieldName); 151 | } 152 | 153 | EquationTransform transform = EquationStore.getInstance().getTransform(equation, variables); 154 | Exception ex = transform.getException(); 155 | if (ex != null) { 156 | effectManager.onError("Error parsing equation: " + equation, ex); 157 | continue; 158 | } 159 | try { 160 | Field field = innerEffect.getClass().getField(fieldName); 161 | parameterTransforms.put(field, transform); 162 | } catch (Exception ex2) { 163 | effectManager.onError("Error binding to field: " + fieldName + " of effect class " + effectClass, ex2); 164 | continue; 165 | } 166 | } 167 | innerEffect.prepare(); 168 | 169 | if (xEquation != null) xTransform = EquationStore.getInstance().getTransform(xEquation, _variables); 170 | if (yEquation != null) yTransform = EquationStore.getInstance().getTransform(yEquation, _variables); 171 | if (zEquation != null) zTransform = EquationStore.getInstance().getTransform(zEquation, _variables); 172 | } 173 | if (innerEffect == null) { 174 | cancel(); 175 | return; 176 | } 177 | 178 | if (origin != null && xTransform != null || yTransform != null || zTransform != null) { 179 | Vector offset = new Vector( 180 | xTransform == null ? 0 : xTransform.get(step, maxIterations, variableA, variableB), 181 | yTransform == null ? 0 : yTransform.get(step, maxIterations, variableA, variableB), 182 | zTransform == null ? 0 : zTransform.get(step, maxIterations, variableA, variableB) 183 | ); 184 | 185 | if (previousOffset != null) { 186 | offset.subtract(previousOffset); 187 | } else { 188 | previousOffset = new Vector(); 189 | } 190 | 191 | Location location = getLocation(); 192 | if (orient && orientPitch) { 193 | offset = VectorUtils.rotateVector(offset, location); 194 | } else if (orient) { 195 | offset = VectorUtils.rotateVector(offset, location.getYaw(), 0); 196 | } 197 | 198 | origin.addOffset(offset); 199 | previousOffset.add(offset); 200 | } 201 | 202 | for (Map.Entry entry : parameterTransforms.entrySet()) { 203 | double value = entry.getValue().get(step, maxIterations, variableA, variableB); 204 | try { 205 | Field field = entry.getKey(); 206 | if (field.getType().equals(Double.class) || field.getType().equals(Double.TYPE)) { 207 | entry.getKey().set(innerEffect,value); 208 | } else if (field.getType().equals(Integer.class) || field.getType().equals(Integer.TYPE)) { 209 | entry.getKey().set(innerEffect, (int)value); 210 | } else if (field.getType().equals(Float.class) || field.getType().equals(Float.TYPE)) { 211 | entry.getKey().set(innerEffect, (float)value); 212 | } else if (field.getType().equals(Short.class) || field.getType().equals(Short.TYPE)) { 213 | entry.getKey().set(innerEffect, (short)value); 214 | } else if (field.getType().equals(Byte.class) || field.getType().equals(Byte.TYPE)) { 215 | entry.getKey().set(innerEffect, (byte)value); 216 | } else { 217 | effectManager.onError("Can't assign property " + entry.getKey().getName() + " of effect class " + effectClass + " of type " + field.getType().getName()); 218 | cancel(); 219 | return; 220 | } 221 | } catch (Exception ex) { 222 | effectManager.onError("Error assigning to : " + entry.getKey().getName() + " of effect class " + effectClass, ex); 223 | cancel(); 224 | return; 225 | } 226 | } 227 | 228 | try { 229 | innerEffect.onRun(); 230 | } catch (Exception ex) { 231 | innerEffect.onDone(); 232 | effectManager.onError(ex); 233 | } 234 | step++; 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/MusicEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import org.bukkit.Location; 8 | 9 | public class MusicEffect extends Effect { 10 | public Particle particle = Particle.NOTE; 11 | 12 | /** 13 | * Radials to spawn next note. 14 | */ 15 | public double radialsPerStep = Math.PI / 8; 16 | 17 | /** 18 | * Radius of circle above head 19 | */ 20 | public float radius = .4f; 21 | 22 | /** 23 | * Current step. Works as a counter 24 | */ 25 | protected float step = 0; 26 | 27 | public MusicEffect(EffectManager effectManager) { 28 | super(effectManager); 29 | type = EffectType.REPEATING; 30 | iterations = 400; 31 | period = 1; 32 | } 33 | 34 | @Override 35 | public void reset() { 36 | this.step = 0; 37 | } 38 | 39 | @Override 40 | public void onRun() { 41 | Location location = getLocation(); 42 | location.add(0, 1.9f, 0); 43 | location.add(Math.cos(radialsPerStep * step) * radius, 0, Math.sin(radialsPerStep * step) * radius); 44 | 45 | display(particle, location); 46 | step++; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/ParticleEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import org.bukkit.Particle; 4 | 5 | import de.slikey.effectlib.Effect; 6 | import de.slikey.effectlib.EffectManager; 7 | import de.slikey.effectlib.EffectType; 8 | 9 | public class ParticleEffect extends Effect { 10 | 11 | /** 12 | * ParticleType of spawned particle 13 | */ 14 | public Particle particle = Particle.VILLAGER_ANGRY; 15 | 16 | public ParticleEffect(EffectManager effectManager) { 17 | super(effectManager); 18 | type = EffectType.REPEATING; 19 | period = 1; 20 | iterations = 1; 21 | } 22 | 23 | @Override 24 | public void onRun() { 25 | display(particle, getLocation()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/PlotEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.math.EquationStore; 7 | import de.slikey.effectlib.math.EquationTransform; 8 | import org.bukkit.Particle; 9 | import org.bukkit.Location; 10 | 11 | import java.util.Arrays; 12 | import java.util.HashSet; 13 | import java.util.Set; 14 | 15 | public class PlotEffect extends Effect { 16 | private final static String[] _variables = {"t", "i"}; 17 | private final static Set variables = new HashSet(Arrays.asList(_variables)); 18 | 19 | /** 20 | * ParticleType of spawned particle 21 | */ 22 | public Particle particle = Particle.REDSTONE; 23 | 24 | /** 25 | * The equation to use for x-values. If not set, the iteration count will be used. 26 | */ 27 | public String xEquation; 28 | 29 | /** 30 | * The equation to use for y-values. If not set, the iteration count will be used. 31 | */ 32 | public String yEquation; 33 | 34 | /** 35 | * The equation to use for y-values. If not set, 0 will be used. 36 | */ 37 | public String zEquation; 38 | 39 | /** 40 | * This is a shortcut to quickly scaling the x value. 41 | */ 42 | public double xScale = 1.0; 43 | 44 | /** 45 | * This is a shortcut to quickly scaling the y value. 46 | */ 47 | public double yScale = 1.0; 48 | 49 | /** 50 | * This is a shortcut to quickly scaling the z value. 51 | */ 52 | public double zScale = 1.0; 53 | 54 | /** 55 | * This will re-spawn particles as the plot moves to make a solid line. 56 | */ 57 | public boolean persistent = true; 58 | 59 | public PlotEffect(EffectManager effectManager) { 60 | super(effectManager); 61 | type = EffectType.REPEATING; 62 | period = 1; 63 | iterations = 100; 64 | } 65 | 66 | private int step = 0; 67 | 68 | @Override 69 | public void onRun() { 70 | int base = persistent ? 0 : step; 71 | for (int i = base; i <= step; i++) { 72 | Location location = getLocation().clone(); 73 | double xOffset = step; 74 | double yOffset = step; 75 | double zOffset = 0; 76 | 77 | if (xEquation != null && !xEquation.isEmpty()) { 78 | EquationTransform xTransform = EquationStore.getInstance().getTransform(xEquation, variables); 79 | xOffset = xTransform.get(i, maxIterations); 80 | } 81 | 82 | if (yEquation != null && !yEquation.isEmpty()) { 83 | EquationTransform yTransform = EquationStore.getInstance().getTransform(yEquation, variables); 84 | yOffset = yTransform.get(i, maxIterations); 85 | } 86 | 87 | if (zEquation != null && !zEquation.isEmpty()) { 88 | EquationTransform zTransform = EquationStore.getInstance().getTransform(zEquation, variables); 89 | zOffset = zTransform.get(i, maxIterations); 90 | } 91 | 92 | location.add(xOffset * xScale, yOffset * yScale, zOffset * zScale); 93 | display(particle, location); 94 | } 95 | 96 | step++; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/PyramidEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.Particle; 5 | import org.bukkit.util.Vector; 6 | 7 | import de.slikey.effectlib.Effect; 8 | import de.slikey.effectlib.EffectManager; 9 | import de.slikey.effectlib.EffectType; 10 | 11 | public class PyramidEffect extends Effect { 12 | 13 | /** 14 | * Particle of the cube 15 | */ 16 | public Particle particle = Particle.FLAME; 17 | 18 | /** 19 | * Particles in each row 20 | */ 21 | public int particles = 8; 22 | 23 | /** 24 | * Center to edge distance 25 | */ 26 | public double radius = 0; 27 | 28 | /** 29 | * Use corners of blocks 30 | */ 31 | public boolean blockSnap = false; 32 | 33 | public PyramidEffect(EffectManager effectManager) { 34 | super(effectManager); 35 | type = EffectType.REPEATING; 36 | period = 5; 37 | iterations = 200; 38 | } 39 | 40 | @Override 41 | public void onRun() { 42 | Location location = getLocation(); 43 | drawOutline(location); 44 | } 45 | 46 | private void drawOutline(Location location) { 47 | Vector v = new Vector(); 48 | for (int i = 0; i < particles; i++) { 49 | // X base 50 | drawEdge(location, v, i, 0, 0, -1); 51 | drawEdge(location, v, i, 0, 0, 1); 52 | 53 | // Z base 54 | drawEdge(location, v, i, -1, 0, 0); 55 | drawEdge(location, v, i, 1, 0, 0); 56 | 57 | // diagonals 58 | drawEdge(location, v, i, -1, 1, -1); 59 | drawEdge(location, v, i, -1, 1, 1); 60 | drawEdge(location, v, i, 1, 1, -1); 61 | drawEdge(location, v, i, 1, 1, 1); 62 | } 63 | } 64 | 65 | private void drawEdge(Location center, Vector v, int i, int dx, int dy, int dz) { 66 | // Y goes from 0 to 1 67 | // X and Z go from -1 to 1 68 | double ratio = (double)i / particles; 69 | if (dy == 1) { 70 | v.setY(ratio); 71 | if (dx < 0) { 72 | v.setX(ratio - 1); 73 | } else { 74 | v.setX(1 - ratio); 75 | } 76 | if (dz < 0) { 77 | v.setZ(ratio - 1); 78 | } else { 79 | v.setZ(1 - ratio); 80 | } 81 | } else { 82 | v.setY(0); 83 | 84 | if (dx == 0) { 85 | v.setX(ratio * 2 - 1); 86 | } else { 87 | v.setX(dx); 88 | } 89 | if (dz == 0) { 90 | v.setZ(ratio * 2 - 1); 91 | } else { 92 | v.setZ(dz); 93 | } 94 | } 95 | display(particle, center.add(v.multiply(radius))); 96 | center.subtract(v); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/ShieldEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | public class ShieldEffect extends Effect { 12 | 13 | /** 14 | * ParticleType of spawned particle 15 | */ 16 | public Particle particle = Particle.FLAME; 17 | 18 | /** 19 | * Radius of the shield 20 | */ 21 | public double radius = 3; 22 | 23 | /** 24 | * Particles to display 25 | */ 26 | public int particles = 50; 27 | 28 | /** 29 | * Set to false for a half-sphere and true for a complete sphere 30 | */ 31 | public boolean sphere = false; 32 | 33 | public ShieldEffect(EffectManager effectManager) { 34 | super(effectManager); 35 | type = EffectType.REPEATING; 36 | iterations = 500; 37 | period = 1; 38 | } 39 | 40 | @Override 41 | public void onRun() { 42 | Location location = getLocation(); 43 | for (int i = 0; i < particles; i++) { 44 | Vector vector = RandomUtils.getRandomVector().multiply(radius); 45 | if (!sphere) { 46 | vector.setY(Math.abs(vector.getY())); 47 | } 48 | location.add(vector); 49 | display(particle, location); 50 | location.subtract(vector); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/SkyRocketEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.EffectManager; 4 | import org.bukkit.entity.Entity; 5 | 6 | public class SkyRocketEffect extends JumpEffect { 7 | 8 | public SkyRocketEffect(EffectManager effectManager) { 9 | super(effectManager); 10 | power = 10; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/SmokeEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import org.bukkit.Location; 9 | 10 | public class SmokeEffect extends Effect { 11 | 12 | /** 13 | * ParticleType of spawned particle 14 | */ 15 | public Particle particle = Particle.SMOKE_NORMAL; 16 | 17 | /** 18 | * Number of particles to display 19 | */ 20 | public int particles = 20; 21 | 22 | public SmokeEffect(EffectManager effectManager) { 23 | super(effectManager); 24 | type = EffectType.REPEATING; 25 | period = 1; 26 | iterations = 300; 27 | } 28 | 29 | @Override 30 | public void onRun() { 31 | Location location = getLocation(); 32 | for (int i = 0; i < particles; i++) { 33 | location.add(RandomUtils.getRandomCircleVector().multiply(RandomUtils.random.nextDouble() * 0.6d)); 34 | location.add(0, RandomUtils.random.nextFloat() * 2, 0); 35 | display(particle, location); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/SoundEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.CustomSound; 7 | 8 | public class SoundEffect extends Effect { 9 | 10 | /** 11 | * Sound effect to play 12 | */ 13 | public CustomSound sound; 14 | 15 | public SoundEffect(EffectManager effectManager) { 16 | super(effectManager); 17 | type = EffectType.REPEATING; 18 | period = 1; 19 | iterations = 1; 20 | } 21 | 22 | @Override 23 | public void onRun() { 24 | if (sound != null) { 25 | sound.play(effectManager.getOwningPlugin(), effectManager.getLogger(), getLocation()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/SphereEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import org.bukkit.Location; 9 | import org.bukkit.util.Vector; 10 | 11 | public class SphereEffect extends Effect { 12 | 13 | /** 14 | * ParticleType of spawned particle 15 | */ 16 | public Particle particle = Particle.SPELL_MOB; 17 | 18 | /** 19 | * Radius of the sphere 20 | */ 21 | public double radius = 0.6; 22 | 23 | /** 24 | * Y-Offset of the sphere 25 | */ 26 | public double yOffset = 0; 27 | 28 | /** 29 | * Particles to display 30 | */ 31 | public int particles = 50; 32 | 33 | /** 34 | * Amount to increase the radius per tick 35 | */ 36 | public double radiusIncrease = 0; 37 | 38 | public SphereEffect(EffectManager effectManager) { 39 | super(effectManager); 40 | type = EffectType.REPEATING; 41 | iterations = 500; 42 | period = 1; 43 | } 44 | 45 | @Override 46 | public void onRun() { 47 | if (radiusIncrease != 0) { 48 | radius += radiusIncrease; 49 | } 50 | 51 | Location location = getLocation(); 52 | location.add(0, yOffset, 0); 53 | for (int i = 0; i < particles; i++) { 54 | Vector vector = RandomUtils.getRandomVector().multiply(radius); 55 | location.add(vector); 56 | display(particle, location); 57 | location.subtract(vector); 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/StarEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.RandomUtils; 9 | import de.slikey.effectlib.util.VectorUtils; 10 | import org.bukkit.Location; 11 | import org.bukkit.util.Vector; 12 | 13 | public class StarEffect extends Effect { 14 | 15 | /** 16 | * Particles to create the star 17 | */ 18 | public Particle particle = Particle.FLAME; 19 | 20 | /** 21 | * Particles per spike 22 | */ 23 | public int particles = 50; 24 | 25 | /** 26 | * Height of the spikes in blocks 27 | */ 28 | public float spikeHeight = 3.5f; 29 | 30 | /** 31 | * Half amount of spikes. Creation is only done half and then mirrored. 32 | */ 33 | public int spikesHalf = 3; 34 | 35 | /** 36 | * Inner radius of the star. (0.5) 37 | */ 38 | public float innerRadius = 0.5f; 39 | 40 | public StarEffect(EffectManager effectManager) { 41 | super(effectManager); 42 | type = EffectType.REPEATING; 43 | period = 4; 44 | iterations = 50; 45 | } 46 | 47 | @Override 48 | public void onRun() { 49 | Location location = getLocation(); 50 | float radius = 3 * innerRadius / MathUtils.SQRT_3; 51 | for (int i = 0; i < spikesHalf * 2; i++) { 52 | double xRotation = i * Math.PI / spikesHalf; 53 | for (int x = 0; x < particles; x++) { 54 | double angle = 2 * Math.PI * x / particles; 55 | float height = RandomUtils.random.nextFloat() * spikeHeight; 56 | Vector v = new Vector(Math.cos(angle), 0, Math.sin(angle)); 57 | v.multiply((spikeHeight - height) * radius / spikeHeight); 58 | v.setY(innerRadius + height); 59 | VectorUtils.rotateAroundAxisX(v, xRotation); 60 | location.add(v); 61 | display(particle, location); 62 | location.subtract(v); 63 | VectorUtils.rotateAroundAxisX(v, Math.PI); 64 | VectorUtils.rotateAroundAxisY(v, Math.PI / 2); 65 | location.add(v); 66 | display(particle, location); 67 | location.subtract(v); 68 | } 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/TextEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.StringParser; 9 | import de.slikey.effectlib.util.VectorUtils; 10 | import java.awt.Color; 11 | import java.awt.Font; 12 | import java.awt.image.BufferedImage; 13 | 14 | import org.bukkit.Location; 15 | import org.bukkit.util.Vector; 16 | 17 | public class TextEffect extends Effect { 18 | 19 | /** 20 | * Particle to draw the text 21 | */ 22 | public Particle particle = Particle.FIREWORKS_SPARK; 23 | 24 | /** 25 | * Text to display 26 | */ 27 | public String text = "Text"; 28 | 29 | /** 30 | * Invert the text 31 | */ 32 | public boolean invert = false; 33 | 34 | /** 35 | * Each stepX pixel will be shown. Saves packets for lower fontsizes. 36 | */ 37 | public int stepX = 1; 38 | 39 | /** 40 | * Each stepY pixel will be shown. Saves packets for lower fontsizes. 41 | */ 42 | public int stepY = 1; 43 | 44 | /** 45 | * Scale the font down 46 | */ 47 | public float size = (float) 1 / 5; 48 | 49 | /** 50 | * Set this only to true if you are working with changing text. I'll advice 51 | * the parser to recalculate the BufferedImage every iteration. 52 | * Recommended FALSE 53 | */ 54 | public boolean realtime = false; 55 | 56 | /** 57 | * Font to create the Text 58 | */ 59 | public Font font; 60 | 61 | /** 62 | * Contains an image version of the String 63 | */ 64 | protected BufferedImage image = null; 65 | 66 | /** 67 | * Track the text used most recently when parsing 68 | */ 69 | private String lastParsedText = null; 70 | 71 | /** 72 | * Track the font used most recently when parsing 73 | */ 74 | private Font lastParsedFont = null; 75 | 76 | public TextEffect(EffectManager effectManager) { 77 | super(effectManager); 78 | this.font = new Font("Tahoma", Font.PLAIN, 16); 79 | type = EffectType.REPEATING; 80 | period = 40; 81 | iterations = 20; 82 | } 83 | 84 | public void setFont(Font font) { 85 | this.font = font; 86 | } 87 | 88 | @Override 89 | public void onRun() { 90 | if (font == null) { 91 | cancel(); 92 | return; 93 | } 94 | Location location = getLocation(); 95 | int clr = 0; 96 | try { 97 | if (image == null || shouldRecalculateImage()) { 98 | lastParsedText = text; 99 | lastParsedFont = font; 100 | // Use last parsed references instead for additional thread safety 101 | image = StringParser.stringToBufferedImage(lastParsedFont, lastParsedText); 102 | } 103 | for (int y = 0; y < image.getHeight(); y += stepY) { 104 | for (int x = 0; x < image.getWidth(); x += stepX) { 105 | clr = image.getRGB(x, y); 106 | if (!invert && Color.black.getRGB() != clr) { 107 | continue; 108 | } else if (invert && Color.black.getRGB() == clr) { 109 | continue; 110 | } 111 | Vector v = new Vector((float) image.getWidth() / 2 - x, (float) image.getHeight() / 2 - y, 0).multiply(size); 112 | VectorUtils.rotateAroundAxisY(v, -location.getYaw() * MathUtils.degreesToRadians); 113 | display(particle, location.add(v)); 114 | location.subtract(v); 115 | } 116 | } 117 | } catch (Exception ex) { 118 | // This seems to happen on bad characters in strings, 119 | // I'm choosing to ignore the exception and cancel the effect for now. 120 | cancel(true); 121 | } 122 | } 123 | 124 | // Replacement for Java 1.7 Objects.equals 125 | public static boolean objectsEquals(Object a, Object b) { 126 | return (a == b) || (a != null && a.equals(b)); 127 | } 128 | 129 | private boolean shouldRecalculateImage() { 130 | // Don't bother if we don't use real time updates 131 | if (!realtime) return false; 132 | 133 | // Text content or font is different, recalculate 134 | return !objectsEquals(lastParsedText, text) || !objectsEquals(lastParsedFont, font); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/TornadoEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import de.slikey.effectlib.util.RandomUtils; 8 | import java.util.ArrayList; 9 | import org.bukkit.Color; 10 | import org.bukkit.Location; 11 | import org.bukkit.util.Vector; 12 | 13 | public class TornadoEffect extends Effect { 14 | 15 | /* 16 | * Tornado particle 17 | */ 18 | public Particle tornadoParticle = Particle.FLAME; 19 | public Color tornadoColor = null; 20 | 21 | /* 22 | * Particle of the cloud 23 | */ 24 | public Particle cloudParticle = Particle.CLOUD; 25 | public Color cloudColor = null; 26 | 27 | /* 28 | * Size of the cloud 29 | */ 30 | public float cloudSize = 2.5f; 31 | 32 | /* 33 | * Y-Offset from location 34 | */ 35 | public double yOffset = .8; 36 | 37 | /* 38 | * Height of the Tornado 39 | */ 40 | public float tornadoHeight = 5f; 41 | 42 | /* 43 | * Max radius of the Tornado 44 | */ 45 | public float maxTornadoRadius = 5f; 46 | 47 | /* 48 | * Should the cloud appear? 49 | */ 50 | public boolean showCloud = true; 51 | 52 | /* 53 | * Should the tornado appear? 54 | */ 55 | public boolean showTornado = true; 56 | 57 | /* 58 | * Distance between each row 59 | */ 60 | public double distance = .375d; 61 | 62 | /* 63 | * Number of particles per circle 64 | */ 65 | public int circleParticles = 64; 66 | 67 | /* 68 | * Number of particles in the cloud 69 | */ 70 | public int cloudParticles = 100; 71 | 72 | /* 73 | * Amount of y-jitter between circle particles 74 | */ 75 | public double circleHeight = 0; 76 | 77 | /* 78 | * Internal counter 79 | */ 80 | protected int step = 0; 81 | 82 | public TornadoEffect(EffectManager manager) { 83 | super(manager); 84 | type = EffectType.REPEATING; 85 | period = 5; 86 | iterations = 20; 87 | } 88 | 89 | @Override 90 | public void reset() { 91 | this.step = 0; 92 | } 93 | 94 | @Override 95 | public void onRun() { 96 | Location l = getLocation().add(0, yOffset, 0); 97 | for (int i = 0; i < (cloudParticles * cloudSize); i++) { 98 | Vector v = RandomUtils.getRandomCircleVector().multiply(RandomUtils.random.nextDouble() * cloudSize); 99 | if (showCloud) { 100 | display(cloudParticle, l.add(v), cloudColor, 0, 7); 101 | l.subtract(v); 102 | } 103 | } 104 | Location t = l.clone().add(0, .2, 0); 105 | double r = .45 * (maxTornadoRadius * (2.35 / tornadoHeight)); 106 | for (double y = 0; y < tornadoHeight; y += distance) { 107 | double fr = r * y; 108 | if (fr > maxTornadoRadius) { 109 | fr = maxTornadoRadius; 110 | } 111 | for (Vector v : createCircle(y, fr)) { 112 | if (showTornado) { 113 | if (circleHeight > 0) { 114 | v.setY(v.getY() + RandomUtils.random.nextDouble() * circleHeight / 2 - circleHeight / 2); 115 | } 116 | display(tornadoParticle, t.add(v), tornadoColor); 117 | t.subtract(v); 118 | step++; 119 | } 120 | } 121 | } 122 | l.subtract(0, yOffset, 0); 123 | } 124 | 125 | public ArrayList createCircle(double y, double radius) { 126 | double amount = radius * circleParticles; 127 | double inc = (2 * Math.PI) / amount; 128 | ArrayList vecs = new ArrayList(); 129 | for (int i = 0; i < amount; i++) { 130 | double angle = i * inc; 131 | double x = radius * Math.cos(angle); 132 | double z = radius * Math.sin(angle); 133 | Vector v = new Vector(x, y, z); 134 | vecs.add(v); 135 | } 136 | return vecs; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/TraceEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import org.bukkit.Location; 10 | import org.bukkit.World; 11 | import org.bukkit.util.Vector; 12 | 13 | public class TraceEffect extends Effect { 14 | 15 | /** 16 | * Particle to spawn 17 | */ 18 | public Particle particle = Particle.FLAME; 19 | 20 | /** 21 | * Iterations to wait before refreshing particles 22 | */ 23 | public int refresh = 5; 24 | 25 | /** 26 | * Maximum amount of way points 27 | */ 28 | public int maxWayPoints = 30; 29 | 30 | /** 31 | * Waypoints of the trace 32 | */ 33 | protected final List wayPoints = new ArrayList(); 34 | 35 | /** 36 | * Internal counter 37 | */ 38 | protected int step = 0; 39 | 40 | /** 41 | * World of the trace 42 | */ 43 | protected World world; 44 | 45 | public TraceEffect(EffectManager effectManager) { 46 | super(effectManager); 47 | type = EffectType.REPEATING; 48 | period = 1; 49 | iterations = 600; 50 | } 51 | 52 | @Override 53 | public void reset() { 54 | this.step = 0; 55 | } 56 | 57 | @Override 58 | public void onRun() { 59 | Location location = getLocation(); 60 | if (world == null) { 61 | world = location.getWorld(); 62 | } else if (!location.getWorld().equals(world)) { 63 | cancel(true); 64 | return; 65 | } 66 | 67 | synchronized(wayPoints) 68 | { 69 | if (wayPoints.size() >= maxWayPoints) { 70 | wayPoints.remove(0); 71 | } 72 | } 73 | 74 | wayPoints.add(location.toVector()); 75 | step++; 76 | if (step % refresh != 0) { 77 | return; 78 | } 79 | 80 | synchronized(wayPoints) 81 | { 82 | for (Vector position : wayPoints) { 83 | Location particleLocation = new Location(world, position.getX(), position.getY(), position.getZ()); 84 | display(particle, particleLocation); 85 | } 86 | } 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/TurnEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Location; 7 | import org.bukkit.entity.Entity; 8 | import org.bukkit.entity.Player; 9 | 10 | public class TurnEffect extends Effect { 11 | 12 | /** 13 | * Angular movement per iteration 14 | */ 15 | public float step = 11.25f; 16 | 17 | public TurnEffect(EffectManager effectManager) { 18 | super(effectManager); 19 | type = EffectType.REPEATING; 20 | period = 1; 21 | iterations = (int) (360 * 5 / step); 22 | asynchronous = false; 23 | } 24 | 25 | @Override 26 | public void onRun() { 27 | Entity entity = getEntity(); 28 | if (entity == null) { 29 | cancel(); 30 | return; 31 | } 32 | Location loc = entity.getLocation(); 33 | loc.setYaw(loc.getYaw() + step); 34 | entity.teleport(loc); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/VortexEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.VectorUtils; 9 | import org.bukkit.Location; 10 | import org.bukkit.util.Vector; 11 | 12 | public class VortexEffect extends Effect { 13 | 14 | /** 15 | * ParticleType of spawned particle 16 | */ 17 | public Particle particle = Particle.FLAME; 18 | 19 | /** 20 | * Radius of vortex (2) 21 | */ 22 | public float radius = 2; 23 | 24 | /** 25 | * Growing per iteration (0.05) 26 | */ 27 | public float grow = .05f; 28 | 29 | /** 30 | * Radials per iteration (PI / 16) 31 | */ 32 | public double radials = Math.PI / 16; 33 | 34 | /** 35 | * Helix-circles per iteration (3) 36 | */ 37 | public int circles = 3; 38 | 39 | /** 40 | * Amount of helices (4) 41 | * Yay for the typo 42 | */ 43 | public int helixes = 4; 44 | 45 | /** 46 | * Current step. Works as counter 47 | */ 48 | protected int step = 0; 49 | 50 | public VortexEffect(EffectManager effectManager) { 51 | super(effectManager); 52 | type = EffectType.REPEATING; 53 | period = 1; 54 | iterations = 200; 55 | } 56 | 57 | @Override 58 | public void reset() { 59 | this.step = 0; 60 | } 61 | 62 | @Override 63 | public void onRun() { 64 | Location location = getLocation(); 65 | for (int x = 0; x < circles; x++) { 66 | for (int i = 0; i < helixes; i++) { 67 | double angle = step * radials + (2 * Math.PI * i / helixes); 68 | Vector v = new Vector(Math.cos(angle) * radius, step * grow, Math.sin(angle) * radius); 69 | VectorUtils.rotateAroundAxisX(v, (location.getPitch() + 90) * MathUtils.degreesToRadians); 70 | VectorUtils.rotateAroundAxisY(v, -location.getYaw() * MathUtils.degreesToRadians); 71 | 72 | location.add(v); 73 | display(particle, location); 74 | location.subtract(v); 75 | } 76 | step++; 77 | } 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/WarpEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import org.bukkit.Particle; 7 | import org.bukkit.Location; 8 | 9 | public class WarpEffect extends Effect { 10 | 11 | /** 12 | * Radius of the spawned circles 13 | */ 14 | public float radius = 1; 15 | 16 | /** 17 | * Particles per circle 18 | */ 19 | public int particles = 20; 20 | 21 | /** 22 | * Particle to display 23 | */ 24 | public Particle particle = Particle.FIREWORKS_SPARK; 25 | 26 | /** 27 | * Interval of the circles 28 | */ 29 | public float grow = .2f; 30 | 31 | /** 32 | * Circles to display 33 | */ 34 | public int rings = 12; 35 | 36 | /** 37 | * Internal counter 38 | */ 39 | protected int step = 0; 40 | 41 | public WarpEffect(EffectManager effectManager) { 42 | super(effectManager); 43 | type = EffectType.REPEATING; 44 | period = 2; 45 | iterations = rings; 46 | } 47 | 48 | @Override 49 | public void reset() { 50 | this.step = 0; 51 | } 52 | 53 | @Override 54 | public void onRun() { 55 | Location location = getLocation(); 56 | if (step > rings) { 57 | step = 0; 58 | } 59 | double x, y, z; 60 | y = step * grow; 61 | location.add(0, y, 0); 62 | for (int i = 0; i < particles; i++) { 63 | double angle = (double) 2 * Math.PI * i / particles; 64 | x = Math.cos(angle) * radius; 65 | z = Math.sin(angle) * radius; 66 | location.add(x, 0, z); 67 | display(particle, location); 68 | location.subtract(x, 0, z); 69 | } 70 | location.subtract(0, y, 0); 71 | step++; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/effect/WaveEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.effect; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.util.MathUtils; 7 | import org.bukkit.Particle; 8 | import de.slikey.effectlib.util.VectorUtils; 9 | import java.util.Collection; 10 | import java.util.HashSet; 11 | import org.bukkit.Color; 12 | import org.bukkit.Location; 13 | import org.bukkit.util.Vector; 14 | 15 | public class WaveEffect extends Effect { 16 | 17 | public Particle particle = Particle.DRIP_WATER; 18 | public Particle cloudParticle = Particle.CLOUD; 19 | public Color cloudColor = null; 20 | 21 | /** 22 | * Velocity of the wave 23 | * Call velocity.zero() if the wave should be stationary 24 | */ 25 | public Vector velocity = new Vector(); 26 | 27 | /** 28 | * Caches the Vectors used to build the wave 29 | */ 30 | protected final Collection waterCache, cloudCache; 31 | 32 | /** 33 | * Amount of particles forming the tube 34 | */ 35 | public int particlesFront = 10; 36 | 37 | /** 38 | * Amount of particles forming the back 39 | */ 40 | public int particlesBack = 10; 41 | 42 | /** 43 | * Rows to build the wave in the width 44 | */ 45 | public int rows = 20; 46 | 47 | /** 48 | * The distance from the origin location to the first point of the wave 49 | */ 50 | public float lengthFront = 1.5f; 51 | 52 | /** 53 | * The distance from the origin location to the last point of the wave 54 | */ 55 | public float lengthBack = 3; 56 | 57 | /** 58 | * Depth of the parabola tube 59 | */ 60 | public float depthFront = 1; 61 | 62 | /** 63 | * Height of the parabola arc forming the back 64 | */ 65 | public float heightBack = .5f; 66 | 67 | /** 68 | * Height of the wave in blocks 69 | */ 70 | public float height = 2; 71 | 72 | /** 73 | * Width of the wave in blocks 74 | */ 75 | public float width = 5; 76 | 77 | /** 78 | * Do not mess with the following attributes. They build a cache to gain performance. 79 | */ 80 | protected boolean firstStep = true; 81 | 82 | public WaveEffect(EffectManager effectManager) { 83 | super(effectManager); 84 | 85 | type = EffectType.REPEATING; 86 | period = 5; 87 | iterations = 50; 88 | waterCache = new HashSet(); 89 | cloudCache = new HashSet(); 90 | } 91 | 92 | @Override 93 | public void reset() { 94 | this.firstStep = true; 95 | } 96 | 97 | /** 98 | * Call this method when you change anything related to the creation of the wave 99 | */ 100 | public void invalidate(Location location) { 101 | firstStep = false; 102 | waterCache.clear(); 103 | cloudCache.clear(); 104 | 105 | Vector s1 = new Vector(-lengthFront, 0, 0); 106 | Vector s2 = new Vector(lengthBack, 0, 0); 107 | Vector h = new Vector(-0.5 * lengthFront, height, 0); 108 | 109 | Vector n1, n2, n_s1ToH, n_s2ToH, c1, c2, s1ToH, s2ToH; 110 | float len_s1ToH, len_s2ToH, yaw; 111 | 112 | s1ToH = h.clone().subtract(s1); 113 | c1 = s1.clone().add(s1ToH.clone().multiply(0.5)); 114 | len_s1ToH = (float) s1ToH.length(); 115 | n_s1ToH = s1ToH.clone().multiply(1f / len_s1ToH); 116 | n1 = new Vector(s1ToH.getY(), -s1ToH.getX(), 0).normalize(); 117 | if (n1.getX() < 0) { 118 | n1.multiply(-1); 119 | } 120 | 121 | s2ToH = h.clone().subtract(s2); 122 | c2 = s2.clone().add(s2ToH.clone().multiply(0.5)); 123 | len_s2ToH = (float) s2ToH.length(); 124 | n_s2ToH = s2ToH.clone().multiply(1f / len_s2ToH); 125 | n2 = new Vector(s2ToH.getY(), -s2ToH.getX(), 0).normalize(); 126 | if (n2.getX() < 0) { 127 | n2.multiply(-1); 128 | } 129 | 130 | yaw = (-location.getYaw() + 90) * MathUtils.degreesToRadians; 131 | 132 | for (int i = 0; i < particlesFront; i++) { 133 | float ratio = (float) i / particlesFront; 134 | float x = (ratio - .5f) * len_s1ToH; 135 | float y = (float) (-depthFront / Math.pow((len_s1ToH / 2), 2) * Math.pow(x, 2) + depthFront); 136 | Vector v = c1.clone(); 137 | v.add(n_s1ToH.clone().multiply(x)); 138 | v.add(n1.clone().multiply(y)); 139 | for (int j = 0; j < rows; j++) { 140 | float z = ((float) j / rows - .5f) * width; 141 | Vector vec = v.clone().setZ(v.getZ() + z); 142 | VectorUtils.rotateAroundAxisY(vec, yaw); 143 | if (i == 0 || i == particlesFront - 1) { 144 | cloudCache.add(vec); 145 | } else { 146 | waterCache.add(vec); 147 | } 148 | } 149 | } 150 | for (int i = 0; i < particlesBack; i++) { 151 | float ratio = (float) i / particlesBack; 152 | float x = (ratio - .5f) * len_s2ToH; 153 | float y = (float) (-heightBack / Math.pow((len_s2ToH / 2), 2) * Math.pow(x, 2) + heightBack); 154 | Vector v = c2.clone(); 155 | v.add(n_s2ToH.clone().multiply(x)); 156 | v.add(n2.clone().multiply(y)); 157 | for (int j = 0; j < rows; j++) { 158 | float z = ((float) j / rows - .5f) * width; 159 | Vector vec = v.clone().setZ(v.getZ() + z); 160 | VectorUtils.rotateAroundAxisY(vec, yaw); 161 | if (i == particlesFront - 1) { 162 | cloudCache.add(vec); 163 | } else { 164 | waterCache.add(vec); 165 | } 166 | } 167 | } 168 | } 169 | 170 | @Override 171 | public void onRun() { 172 | Location location = getLocation(); 173 | if (firstStep) { 174 | velocity.copy(location.getDirection().setY(0).normalize().multiply(0.2)); 175 | invalidate(location); 176 | } 177 | location.add(velocity); 178 | 179 | for (Vector v : cloudCache) { 180 | location.add(v); 181 | display(cloudParticle, location, cloudColor, 0, 1); 182 | location.subtract(v); 183 | } 184 | for (Vector v : waterCache) { 185 | location.add(v); 186 | display(particle, location); 187 | location.subtract(v); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/ConstantTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | 5 | public class ConstantTransform implements Transform { 6 | 7 | private double value; 8 | 9 | public ConstantTransform() { 10 | 11 | } 12 | 13 | public ConstantTransform(double value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public void load(ConfigurationSection parameters) { 19 | value = parameters.getDouble("value"); 20 | } 21 | 22 | @Override 23 | public double get(double t) { 24 | return value; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/EchoTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | 5 | public class EchoTransform implements Transform { 6 | @Override 7 | public void load(ConfigurationSection parameters) { 8 | } 9 | 10 | @Override 11 | public double get(double t) { 12 | return t; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/EquationStore.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import java.util.Collection; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import org.apache.commons.lang.StringUtils; 8 | 9 | public class EquationStore { 10 | private static final String DEFAULT_VARIABLE = "x"; 11 | private static EquationStore instance; 12 | private Map transforms = new HashMap(); 13 | 14 | public EquationTransform getTransform(String equation) { 15 | return getTransform(equation, DEFAULT_VARIABLE); 16 | } 17 | 18 | public EquationTransform getTransform(String equation, String variable) { 19 | EquationTransform transform = transforms.get(equation); 20 | if (transform == null) { 21 | transform = new EquationTransform(equation, variable); 22 | transforms.put(equation, transform); 23 | } 24 | 25 | return transform; 26 | } 27 | 28 | public EquationTransform getTransform(String equation, String... variables) { 29 | String equationKey = equation + ":" + StringUtils.join(variables, ","); 30 | EquationTransform transform = transforms.get(equationKey); 31 | if (transform == null) { 32 | transform = new EquationTransform(equation, variables); 33 | transforms.put(equationKey, transform); 34 | } 35 | 36 | return transform; 37 | } 38 | 39 | public EquationTransform getTransform(String equation, Collection variables) { 40 | String equationKey = equation + ":" + StringUtils.join(variables, ","); 41 | EquationTransform transform = transforms.get(equationKey); 42 | if (transform == null) { 43 | transform = new EquationTransform(equation, variables); 44 | transforms.put(equationKey, transform); 45 | } 46 | 47 | return transform; 48 | } 49 | 50 | public static void clear() { 51 | if (instance != null) { 52 | instance.transforms.clear(); 53 | } 54 | } 55 | 56 | public static EquationStore getInstance() { 57 | if (instance == null) { 58 | instance = new EquationStore(); 59 | } 60 | 61 | return instance; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/EquationTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.HashSet; 6 | import java.util.Random; 7 | 8 | import org.bukkit.configuration.ConfigurationSection; 9 | 10 | import net.objecthunter.exp4j.Expression; 11 | import net.objecthunter.exp4j.ExpressionBuilder; 12 | import net.objecthunter.exp4j.function.Function; 13 | 14 | public class EquationTransform implements Transform { 15 | private Expression expression; 16 | private static Function randFunction; 17 | private static Function minFunction; 18 | private static Function maxFunction; 19 | private static Function selectFunction; 20 | private final Collection inputVariables; 21 | private Exception exception; 22 | 23 | @Override 24 | public void load(ConfigurationSection parameters) { 25 | setEquation(parameters.getString("equation", "")); 26 | } 27 | 28 | public EquationTransform() { 29 | inputVariables = new ArrayList(); 30 | } 31 | 32 | public EquationTransform(String equation) { 33 | this(equation, "t"); 34 | } 35 | 36 | public EquationTransform(String equation, String inputVariable) { 37 | inputVariables = new ArrayList(); 38 | inputVariables.add(inputVariable); 39 | setEquation(equation); 40 | } 41 | 42 | public EquationTransform(String equation, String... inputVariables) { 43 | this.inputVariables = new ArrayList(); 44 | for (String inputVariable : inputVariables) { 45 | this.inputVariables.add(inputVariable); 46 | } 47 | setEquation(equation); 48 | } 49 | 50 | public EquationTransform(String equation, Collection inputVariables) { 51 | this.inputVariables = inputVariables; 52 | setEquation(equation); 53 | } 54 | 55 | private void checkCustomFunctions() { 56 | if (randFunction == null) { 57 | randFunction = new Function("rand", 2) { 58 | private Random random = new Random(); 59 | 60 | @Override 61 | public double apply(double... args) { 62 | return random.nextDouble() * (args[1] - args[0]) + args[0]; 63 | } 64 | }; 65 | } 66 | if (minFunction == null) { 67 | minFunction = new Function("min", 2) { 68 | @Override 69 | public double apply(double... args) { 70 | return Math.min(args[0], args[1]); 71 | } 72 | }; 73 | } 74 | if (maxFunction == null) { 75 | maxFunction = new Function("max", 2) { 76 | @Override 77 | public double apply(double... args) { 78 | return Math.max(args[0], args[1]); 79 | } 80 | }; 81 | } 82 | if (selectFunction == null) { 83 | selectFunction = new Function("select", 4) { 84 | @Override 85 | public double apply(double... args) { 86 | if (args[0] < 0) return args[1]; 87 | else if (args[0] == 0) return args[2]; 88 | return args[3]; 89 | } 90 | }; 91 | } 92 | } 93 | 94 | public boolean setEquation(String equation) { 95 | try { 96 | checkCustomFunctions(); 97 | exception = null; 98 | expression = new ExpressionBuilder(equation) 99 | .function(randFunction) 100 | .function(minFunction) 101 | .function(maxFunction) 102 | .function(selectFunction) 103 | .variables(new HashSet(inputVariables)) 104 | .build(); 105 | } catch (Exception ex) { 106 | expression = null; 107 | exception = ex; 108 | } 109 | 110 | return exception == null; 111 | } 112 | 113 | @Override 114 | public double get(double t) { 115 | if (expression == null) { 116 | return 0; 117 | } 118 | for (String inputVariable : inputVariables) { 119 | expression.setVariable(inputVariable, t); 120 | } 121 | return get(); 122 | } 123 | 124 | public double get(double... t) { 125 | if (expression == null) { 126 | return 0; 127 | } 128 | int index = 0; 129 | for (String inputVariable : inputVariables) { 130 | expression.setVariable(inputVariable, t[index]); 131 | if (index < t.length - 1) index++; 132 | } 133 | return get(); 134 | } 135 | 136 | public void addVariable(String key) { 137 | inputVariables.add(key); 138 | } 139 | 140 | public void setVariable(String key, double value) { 141 | if (expression != null) { 142 | expression.setVariable(key, value); 143 | } 144 | } 145 | 146 | public double get() { 147 | if (expression == null) { 148 | return Double.NaN; 149 | } 150 | double value = Double.NaN; 151 | try { 152 | exception = null; 153 | value = expression.evaluate(); 154 | } catch (Exception ex) { 155 | exception = ex; 156 | } 157 | return value; 158 | } 159 | 160 | public Exception getException() { 161 | return exception; 162 | } 163 | 164 | public boolean isValid() { 165 | return exception == null; 166 | } 167 | 168 | public Collection getParameters() { 169 | return inputVariables; 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/MultiplyTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | 5 | import java.util.Collection; 6 | 7 | public class MultiplyTransform implements Transform { 8 | private Collection inputs; 9 | 10 | @Override 11 | public void load(ConfigurationSection parameters) { 12 | inputs = Transforms.loadTransformList(parameters, "inputs"); 13 | } 14 | 15 | @Override 16 | public double get(double t) { 17 | double value = 1; 18 | for (Transform transform : inputs) { 19 | value *= transform.get(t); 20 | } 21 | return value; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/SequenceTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import de.slikey.effectlib.util.ConfigUtils; 4 | import org.bukkit.configuration.ConfigurationSection; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collection; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | public class SequenceTransform implements Transform { 12 | private List steps; 13 | 14 | private static class Sequence { 15 | private final Transform transform; 16 | private final double start; 17 | 18 | public Sequence(ConfigurationSection configuration) { 19 | this.transform = Transforms.loadTransform(configuration, "transform"); 20 | this.start = configuration.getDouble("start", 0); 21 | } 22 | 23 | public double getStart() { 24 | return start; 25 | } 26 | 27 | public double get(double t) { 28 | return transform.get(t); 29 | } 30 | }; 31 | 32 | @Override 33 | public void load(ConfigurationSection parameters) { 34 | steps = new ArrayList(); 35 | Collection stepConfigurations = ConfigUtils.getNodeList(parameters, "steps"); 36 | if (stepConfigurations != null) { 37 | for (ConfigurationSection stepConfig : stepConfigurations) { 38 | steps.add(new Sequence(stepConfig)); 39 | } 40 | } 41 | Collections.reverse(steps); 42 | } 43 | 44 | @Override 45 | public double get(double t) { 46 | double value = 0; 47 | for (Sequence step : steps) { 48 | if (step.getStart() <= t) { 49 | return step.get(t); 50 | } 51 | } 52 | return value; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/SumTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | 5 | import java.util.Collection; 6 | 7 | public class SumTransform implements Transform { 8 | private Collection inputs; 9 | 10 | @Override 11 | public void load(ConfigurationSection parameters) { 12 | inputs = Transforms.loadTransformList(parameters, "inputs"); 13 | } 14 | 15 | @Override 16 | public double get(double t) { 17 | double value = 0; 18 | for (Transform transform : inputs) { 19 | value += transform.get(t); 20 | } 21 | return value; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/Transform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | 5 | public interface Transform { 6 | public void load(ConfigurationSection parameters); 7 | public double get(double t); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/Transforms.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import de.slikey.effectlib.EffectManager; 4 | import de.slikey.effectlib.util.ConfigUtils; 5 | import org.bukkit.configuration.ConfigurationSection; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Collection; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | public class Transforms { 14 | private static final String TRANSFORM_BUILTIN_CLASSPATH = "de.slikey.effectlib.math"; 15 | private static Map> transformClasses = new HashMap>(); 16 | private static EffectManager effectManager; 17 | 18 | public static Transform loadTransform(ConfigurationSection base, String value) { 19 | if (base.isConfigurationSection(value)) { 20 | return loadTransform(ConfigUtils.getConfigurationSection(base, value)); 21 | } 22 | if (base.isDouble(value) || base.isInt(value)) { 23 | return new ConstantTransform(base.getDouble(value)); 24 | } 25 | if (base.isString(value)) { 26 | String equation = base.getString(value); 27 | if (equation.equalsIgnoreCase("t") || equation.equalsIgnoreCase("time")) { 28 | return new EchoTransform(); 29 | } 30 | EquationTransform transform = EquationStore.getInstance().getTransform(equation, "t"); 31 | Exception ex = transform.getException(); 32 | if (ex != null && effectManager != null) { 33 | effectManager.onError("Error parsing equation: " + equation, ex); 34 | } 35 | return transform; 36 | } 37 | return new ConstantTransform(0); 38 | } 39 | 40 | public static Collection loadTransformList(ConfigurationSection base, String value) 41 | { 42 | Collection transformConfigs = ConfigUtils.getNodeList(base, value); 43 | List transforms = new ArrayList(); 44 | if (transformConfigs != null) 45 | { 46 | for (ConfigurationSection transformConfig : transformConfigs) 47 | { 48 | transforms.add(loadTransform(transformConfig)); 49 | } 50 | } 51 | 52 | return transforms; 53 | } 54 | 55 | public static Transform loadTransform(ConfigurationSection parameters) { 56 | Transform transform = null; 57 | if (parameters != null && parameters.contains("class")) 58 | { 59 | String className = parameters.getString("class"); 60 | try 61 | { 62 | if (!className.contains(".")) 63 | { 64 | className = TRANSFORM_BUILTIN_CLASSPATH + "." + className; 65 | } 66 | Class genericClass = transformClasses.get(className); 67 | if (genericClass == null) { 68 | try { 69 | genericClass = Class.forName(className + "Transform"); 70 | } catch (Exception ex) { 71 | genericClass = Class.forName(className); 72 | } 73 | 74 | if (!Transform.class.isAssignableFrom(genericClass)) { 75 | throw new Exception("Must extend Transform"); 76 | } 77 | transformClasses.put(className, genericClass); 78 | } 79 | 80 | @SuppressWarnings("unchecked") 81 | Class transformClass = (Class)genericClass; 82 | transform = transformClass.newInstance(); 83 | parameters.set("class", null); 84 | transform.load(parameters); 85 | } catch (Exception ex) { 86 | if (effectManager != null) { 87 | effectManager.onError("Error loading class " + className, ex); 88 | } 89 | } 90 | } 91 | 92 | return transform == null ? new ConstantTransform(0) : transform; 93 | } 94 | 95 | public static void setEffectManager(EffectManager manager) { 96 | effectManager = manager; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/VectorTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import de.slikey.effectlib.util.VectorUtils; 4 | import org.bukkit.Location; 5 | import org.bukkit.configuration.ConfigurationSection; 6 | import org.bukkit.util.Vector; 7 | 8 | public class VectorTransform { 9 | private Transform xTransform; 10 | private Transform yTransform; 11 | private Transform zTransform; 12 | private boolean orient; 13 | 14 | public VectorTransform(ConfigurationSection configuration) { 15 | xTransform = Transforms.loadTransform(configuration, "x"); 16 | yTransform = Transforms.loadTransform(configuration, "y"); 17 | zTransform = Transforms.loadTransform(configuration, "z"); 18 | orient = configuration.getBoolean("orient", true); 19 | } 20 | 21 | public Vector get(Location source, double t) { 22 | // This returns a unit vector with the new direction calculated via the equations 23 | Double xValue = xTransform.get(t); 24 | Double yValue = yTransform.get(t); 25 | Double zValue = zTransform.get(t); 26 | 27 | Vector result = new Vector(xValue, yValue, zValue); 28 | 29 | // Rotates to player's direction 30 | if (orient && source != null) 31 | { 32 | result = VectorUtils.rotateVector(result, source); 33 | } 34 | 35 | return result; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/dQuadraticTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | 5 | public class dQuadraticTransform implements Transform { 6 | private Transform a; 7 | private Transform b; 8 | private Transform c; 9 | 10 | @Override 11 | public void load(ConfigurationSection parameters) { 12 | a = Transforms.loadTransform(parameters, "a"); 13 | b = Transforms.loadTransform(parameters, "b"); 14 | c = Transforms.loadTransform(parameters, "c"); 15 | } 16 | 17 | /** 18 | * This returns the derivative, or velocity, of a quadratic equation at a specific step. 19 | * For a quadratic function: 20 | * f(x) = a(x+b)^2 + c(x+b) + d 21 | * f'(x) = 2a(x+b) + c 22 | * @param t 23 | * @return 24 | */ 25 | @Override 26 | public double get(double t) { 27 | return 2 * a.get(t) * (t + b.get(t)) + c.get(t); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/math/dSinTransform.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.math; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | 5 | public class dSinTransform implements Transform { 6 | private Transform a; 7 | private Transform b; 8 | private Transform c; 9 | 10 | @Override 11 | public void load(ConfigurationSection parameters) { 12 | a = Transforms.loadTransform(parameters, "a"); 13 | b = Transforms.loadTransform(parameters, "b"); 14 | c = Transforms.loadTransform(parameters, "c"); 15 | } 16 | 17 | /** 18 | * This returns the derivative, or velocity, of a sin equation at a specific step. 19 | * For a sin function: 20 | * f(x) = a*sin(b(x+c)) + d 21 | * f'(x) = a*b*cos(b(x+c)) 22 | * @param t 23 | * @return 24 | */ 25 | @Override 26 | public double get(double t) { 27 | double bValue = b.get(t); 28 | return a.get(t) * bValue * Math.cos(bValue * (t + c.get(t))); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/BaseImageEffect.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import de.slikey.effectlib.Effect; 4 | import de.slikey.effectlib.EffectManager; 5 | import de.slikey.effectlib.EffectType; 6 | import de.slikey.effectlib.effect.ColoredImageEffect; 7 | import org.bukkit.Location; 8 | import org.bukkit.Particle; 9 | import org.bukkit.util.Vector; 10 | 11 | import java.awt.image.BufferedImage; 12 | import java.io.File; 13 | 14 | public abstract class BaseImageEffect extends Effect { 15 | 16 | /** 17 | * Particle to draw the image 18 | */ 19 | public Particle particle = Particle.REDSTONE; 20 | 21 | /** 22 | * For configuration-driven files 23 | */ 24 | public String fileName = null; 25 | 26 | /** 27 | * Whether or not to check for transparent pixels 28 | */ 29 | public boolean transparency = false; 30 | 31 | /** 32 | * How many ticks to show each frame 33 | */ 34 | public int frameDelay = 5; 35 | 36 | /** 37 | * Each stepX pixel will be shown. Saves packets for high resolutions. 38 | */ 39 | public int stepX = 10; 40 | 41 | /** 42 | * Each stepY pixel will be shown. Saves packets for high resolutions. 43 | */ 44 | public int stepY = 10; 45 | 46 | /** 47 | * Scale the image down 48 | */ 49 | public float size = (float) 1 / 40; 50 | 51 | /** 52 | * Should it rotate? 53 | */ 54 | public boolean enableRotation = true; 55 | 56 | /** 57 | * Apply a fixed rotation 58 | */ 59 | public Vector rotation = null; 60 | 61 | /** 62 | * Should it orient to face the player's direction? 63 | */ 64 | public boolean orient = true; 65 | 66 | /** 67 | * Should it face in the same direction as the location. Obeying yaw and pitch? 68 | */ 69 | public boolean orientPitch = false; 70 | 71 | /** 72 | * What plane should it rotate? 73 | */ 74 | public ColoredImageEffect.Plane plane = ColoredImageEffect.Plane.XYZ; 75 | 76 | /** 77 | * Turns the cube by this angle each iteration around the x-axis 78 | */ 79 | public double angularVelocityX = Math.PI / 200; 80 | 81 | /** 82 | * Turns the cube by this angle each iteration around the y-axis 83 | */ 84 | public double angularVelocityY = Math.PI / 170; 85 | 86 | /** 87 | * Turns the cube by this angle each iteration around the z-axis 88 | */ 89 | public double angularVelocityZ = Math.PI / 155; 90 | 91 | /** 92 | * Image as BufferedImage 93 | */ 94 | protected BufferedImage[] images = null; 95 | 96 | /** 97 | * Step counter 98 | */ 99 | protected int step = 0; 100 | 101 | /** 102 | * Rotation step counter 103 | */ 104 | protected int rotationStep = 0; 105 | 106 | /** 107 | * Delay between steps 108 | */ 109 | protected int stepDelay = 0; 110 | 111 | protected ImageLoadCallback imageLoadCallback; 112 | 113 | public BaseImageEffect(EffectManager effectManager) { 114 | super(effectManager); 115 | type = EffectType.REPEATING; 116 | period = 2; 117 | iterations = 200; 118 | } 119 | 120 | @Override 121 | public void reset() { 122 | this.step = 0; 123 | this.rotationStep = 0; 124 | } 125 | 126 | public void load(String fileName) { 127 | imageLoadCallback = new ImageLoadCallback() { 128 | @Override 129 | public void loaded(BufferedImage[] i) { 130 | images = i; 131 | imageLoadCallback = null; 132 | } 133 | }; 134 | effectManager.loadImage(fileName, imageLoadCallback); 135 | } 136 | 137 | public void loadFile(File file) { 138 | load(file.getName()); 139 | } 140 | 141 | @Override 142 | public void onRun() { 143 | if (images == null && imageLoadCallback != null) { 144 | return; 145 | } 146 | if (images == null && fileName != null) { 147 | load(fileName); 148 | return; 149 | } 150 | if (images == null || images.length == 0) { 151 | cancel(); 152 | return; 153 | } 154 | 155 | if (stepDelay == frameDelay) { 156 | step++; 157 | stepDelay = 0; 158 | } 159 | stepDelay++; 160 | 161 | if (step >= images.length) { 162 | step = 0; 163 | } 164 | BufferedImage image = images[step]; 165 | 166 | Location location = getLocation(); 167 | for (int y = 0; y < image.getHeight(); y += stepY) { 168 | for (int x = 0; x < image.getWidth(); x += stepX) { 169 | Vector v = new Vector((float) image.getWidth() / 2 - x, (float) image.getHeight() / 2 - y, 0).multiply(size); 170 | if (rotation != null) { 171 | VectorUtils.rotateVector(v, rotation.getX() * MathUtils.degreesToRadians, rotation.getY() * MathUtils.degreesToRadians, rotation.getZ() * MathUtils.degreesToRadians); 172 | } 173 | if (orient) { 174 | VectorUtils.rotateAroundAxisY(v, -location.getYaw() * MathUtils.degreesToRadians); 175 | } 176 | if (orientPitch) { 177 | VectorUtils.rotateVector(v, location); 178 | } 179 | if (enableRotation) { 180 | double rotX = 0; 181 | double rotY = 0; 182 | double rotZ = 0; 183 | switch (plane) { 184 | case X: 185 | rotX = angularVelocityX * rotationStep; 186 | break; 187 | case Y: 188 | rotY = angularVelocityY * rotationStep; 189 | break; 190 | case Z: 191 | rotZ = angularVelocityZ * rotationStep; 192 | break; 193 | case XY: 194 | rotX = angularVelocityX * rotationStep; 195 | rotY = angularVelocityY * rotationStep; 196 | break; 197 | case XZ: 198 | rotX = angularVelocityX * rotationStep; 199 | rotZ = angularVelocityZ * rotationStep; 200 | break; 201 | case XYZ: 202 | rotX = angularVelocityX * rotationStep; 203 | rotY = angularVelocityY * rotationStep; 204 | rotZ = angularVelocityZ * rotationStep; 205 | break; 206 | case YZ: 207 | rotY = angularVelocityY * rotationStep; 208 | rotZ = angularVelocityZ * step; 209 | break; 210 | } 211 | VectorUtils.rotateVector(v, rotX, rotY, rotZ); 212 | } 213 | 214 | int pixel = image.getRGB(x, y); 215 | if (transparency && (pixel >> 24) == 0) { 216 | continue; 217 | } 218 | 219 | display(image, v, location, pixel); 220 | } 221 | } 222 | rotationStep++; 223 | } 224 | 225 | public enum Plane { 226 | 227 | X, Y, Z, XY, XZ, XYZ, YZ; 228 | } 229 | 230 | protected abstract void display(BufferedImage image, Vector v, Location location, int pixel); 231 | } 232 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/ConfigUtils.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import org.bukkit.configuration.ConfigurationSection; 4 | import org.bukkit.configuration.MemoryConfiguration; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collection; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public class ConfigUtils { 12 | public static Collection getNodeList(ConfigurationSection node, String path) { 13 | Collection results = new ArrayList(); 14 | List> mapList = node.getMapList(path); 15 | for (Map map : mapList) { 16 | results.add(toConfigurationSection(map)); 17 | } 18 | 19 | return results; 20 | } 21 | 22 | @Deprecated 23 | public static ConfigurationSection toNodeList(Map nodeMap) { 24 | return toConfigurationSection(nodeMap); 25 | } 26 | 27 | public static ConfigurationSection toConfigurationSection(Map nodeMap) { 28 | ConfigurationSection newSection = new MemoryConfiguration(); 29 | for (Map.Entry entry : nodeMap.entrySet()) { 30 | set(newSection, entry.getKey().toString(), entry.getValue()); 31 | } 32 | 33 | return newSection; 34 | } 35 | 36 | public static ConfigurationSection toStringConfiguration(Map stringMap) { 37 | if (stringMap == null) { 38 | return null; 39 | } 40 | ConfigurationSection configMap = new MemoryConfiguration(); 41 | for (Map.Entry entry : stringMap.entrySet()) { 42 | configMap.set(entry.getKey(), entry.getValue()); 43 | } 44 | 45 | return configMap; 46 | } 47 | 48 | 49 | public static void set(ConfigurationSection node, String path, Object value) 50 | { 51 | if (value == null) { 52 | node.set(path, null); 53 | return; 54 | } 55 | 56 | boolean isTrue = value.equals("true"); 57 | boolean isFalse = value.equals("false"); 58 | if (isTrue || isFalse) { 59 | node.set(path, isTrue); 60 | } else { 61 | try { 62 | Integer i = (value instanceof Integer) ? (Integer)value : Integer.parseInt(value.toString()); 63 | node.set(path, i); 64 | } catch (Exception ex) { 65 | try { 66 | Double d; 67 | if (value instanceof Double) { 68 | d = (Double)value; 69 | } else if (value instanceof Float) { 70 | d = (double)(Float)value; 71 | } else { 72 | d = Double.parseDouble(value.toString()); 73 | } 74 | node.set(path, d); 75 | } catch (Exception ex2) { 76 | node.set(path, value); 77 | } 78 | } 79 | } 80 | } 81 | 82 | public static ConfigurationSection getConfigurationSection(ConfigurationSection base, String key) 83 | { 84 | ConfigurationSection section = base.getConfigurationSection(key); 85 | if (section != null) { 86 | return section; 87 | } 88 | Object value = base.get(key); 89 | if (value == null) return null; 90 | 91 | if (value instanceof ConfigurationSection) 92 | { 93 | return (ConfigurationSection)value; 94 | } 95 | 96 | if (value instanceof Map) 97 | { 98 | ConfigurationSection newChild = base.createSection(key); 99 | @SuppressWarnings("unchecked") 100 | Map map = (Map)value; 101 | for (Map.Entry entry : map.entrySet()) 102 | { 103 | newChild.set(entry.getKey(), entry.getValue()); 104 | } 105 | base.set(key, newChild); 106 | return newChild; 107 | } 108 | 109 | return null; 110 | } 111 | 112 | public static boolean isMaxValue(String stringValue) { 113 | return stringValue.equalsIgnoreCase("infinite") 114 | || stringValue.equalsIgnoreCase("forever") 115 | || stringValue.equalsIgnoreCase("infinity") 116 | || stringValue.equalsIgnoreCase("max"); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/Disposable.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | public interface Disposable { 4 | 5 | public void dispose(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/DynamicLocation.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import java.lang.ref.WeakReference; 4 | import org.bukkit.Location; 5 | import org.bukkit.entity.Entity; 6 | import org.bukkit.entity.LivingEntity; 7 | import org.bukkit.util.Vector; 8 | 9 | /** 10 | * Represents a Location that can move, possibly bound to an Entity. 11 | */ 12 | public class DynamicLocation { 13 | private final Location location; 14 | private final Location originalLocation; 15 | private final WeakReference entity; 16 | private float yawOffset; 17 | private float pitchOffset; 18 | private Vector offset; 19 | private Vector relativeOffset; 20 | private Vector entityOffset; 21 | private boolean updateLocation = true; 22 | private boolean updateDirection = true; 23 | private Float yaw = null; 24 | private Float pitch = null; 25 | 26 | public DynamicLocation(Location location) { 27 | if (location != null) { 28 | this.location = location.clone(); 29 | } else { 30 | this.location = null; 31 | } 32 | this.originalLocation = location; 33 | this.entity = null; 34 | } 35 | 36 | public DynamicLocation(Entity entity) { 37 | if (entity != null) { 38 | this.entity = new WeakReference(entity); 39 | this.location = getEntityLocation(entity); 40 | } else { 41 | this.entity = null; 42 | this.location = null; 43 | } 44 | this.originalLocation = location; 45 | } 46 | 47 | public DynamicLocation(Location location, Entity entity) { 48 | if (location != null) { 49 | this.location = location.clone(); 50 | } else if (entity != null) { 51 | this.location = getEntityLocation(entity); 52 | } else { 53 | this.location = null; 54 | } 55 | if (entity != null) { 56 | this.entity = new WeakReference(entity); 57 | this.entityOffset = this.location.toVector().subtract(getEntityLocation(entity).toVector()); 58 | } else { 59 | this.entity = null; 60 | } 61 | this.originalLocation = this.location == null ? null : this.location.clone(); 62 | } 63 | 64 | public void addOffset(Vector offset) { 65 | if (this.offset == null) { 66 | this.offset = offset.clone(); 67 | } else { 68 | this.offset.add(offset); 69 | } 70 | this.updateOffsets(); 71 | } 72 | 73 | public void addRelativeOffset(Vector offset) { 74 | if (this.relativeOffset == null) { 75 | this.relativeOffset = offset.clone(); 76 | } else { 77 | this.relativeOffset.add(offset); 78 | } 79 | this.updateOffsets(); 80 | } 81 | 82 | public Entity getEntity() { 83 | return entity == null ? null : entity.get(); 84 | } 85 | 86 | public Location getLocation() { 87 | return location; 88 | } 89 | 90 | protected Location getEntityLocation(Entity entity) { 91 | if (entity instanceof LivingEntity) { 92 | return ((LivingEntity) entity).getEyeLocation(); 93 | } 94 | return entity.getLocation(); 95 | } 96 | 97 | public void setDirection(Vector direction) { 98 | location.setDirection(direction); 99 | updateDirection(); 100 | } 101 | 102 | public void updateDirection() { 103 | if (yaw != null) { 104 | location.setYaw(yaw); 105 | } 106 | if (pitch != null) { 107 | location.setPitch(pitch); 108 | } 109 | if (yawOffset != 0) { 110 | location.setYaw(location.getYaw() + yawOffset); 111 | } 112 | if (pitchOffset != 0) { 113 | location.setPitch(location.getPitch() + pitchOffset); 114 | } 115 | } 116 | 117 | public void updateFrom(Location newLocation) { 118 | if (originalLocation != null) { 119 | originalLocation.setX(newLocation.getX()); 120 | originalLocation.setY(newLocation.getY()); 121 | originalLocation.setZ(newLocation.getZ()); 122 | } 123 | updateOffsets(); 124 | } 125 | 126 | public void updateOffsets() { 127 | if (originalLocation == null || location == null) return; 128 | location.setX(originalLocation.getX()); 129 | location.setY(originalLocation.getY()); 130 | location.setZ(originalLocation.getZ()); 131 | if (offset != null) { 132 | location.add(offset); 133 | } 134 | if (relativeOffset != null) { 135 | location.add(VectorUtils.rotateVector(relativeOffset, location)); 136 | } 137 | if (entityOffset != null) { 138 | location.add(entityOffset); 139 | } 140 | } 141 | 142 | public void setUpdateLocation(boolean update) { 143 | updateLocation = update; 144 | } 145 | 146 | public void update() { 147 | if (location == null || (!updateLocation && !updateDirection)) { 148 | return; 149 | } 150 | 151 | Entity entityReference = entity == null ? null : entity.get(); 152 | if (entityReference != null) { 153 | Location currentLocation = getEntityLocation(entityReference); 154 | if (updateDirection) 155 | { 156 | setDirection(currentLocation.getDirection()); 157 | } 158 | if (updateLocation) 159 | { 160 | updateFrom(currentLocation); 161 | } 162 | } 163 | } 164 | 165 | public void setUpdateDirection(boolean updateDirection) { 166 | this.updateDirection = updateDirection; 167 | } 168 | 169 | public void setDirectionOffset(float yawOffset, float pitchOffset) { 170 | this.pitchOffset = pitchOffset; 171 | this.yawOffset = yawOffset; 172 | } 173 | 174 | public void setPitch(Float pitch) { 175 | this.pitch = pitch; 176 | } 177 | 178 | public void setYaw(Float yaw) { 179 | this.yaw = yaw; 180 | } 181 | 182 | public boolean hasValidEntity() { 183 | Entity entity = this.getEntity(); 184 | return entity != null && entity.isValid(); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/ImageLoadCallback.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import java.awt.image.BufferedImage; 4 | 5 | public interface ImageLoadCallback { 6 | void loaded(final BufferedImage[] images); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/ImageLoadTask.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import de.slikey.effectlib.EffectManager; 4 | 5 | import javax.imageio.ImageIO; 6 | import javax.imageio.ImageReader; 7 | import javax.imageio.stream.ImageInputStream; 8 | import java.awt.image.BufferedImage; 9 | import java.io.File; 10 | import java.io.FileOutputStream; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | import java.net.HttpURLConnection; 14 | import java.net.URL; 15 | import java.net.URLEncoder; 16 | import java.util.logging.Level; 17 | 18 | public class ImageLoadTask implements Runnable { 19 | private static final int REQUEST_TIMEOUT = 30000; 20 | private static final int BUFFER_SIZE = 10 * 1024; 21 | private static boolean dirsMade = false; 22 | private final String fileName; 23 | private final ImageLoadCallback callback; 24 | private final EffectManager effectManager; 25 | 26 | public ImageLoadTask(EffectManager manager, String fileName, ImageLoadCallback callback) { 27 | this.fileName = fileName; 28 | this.callback = callback; 29 | this.effectManager = manager; 30 | } 31 | 32 | @Override 33 | public void run() { 34 | BufferedImage[] images; 35 | File imageFile; 36 | if (fileName.startsWith("http")) { 37 | try { 38 | File cacheFolder = effectManager.getImageCacheFolder(); 39 | if (cacheFolder == null) { 40 | // This should never really happen anymore, but leaving the check here just in case. 41 | effectManager.getLogger().log(Level.WARNING, "Can't load from URL because no cache folder has been set by the owning plugin: " + fileName); 42 | callback.loaded(new BufferedImage[0]); 43 | return; 44 | } 45 | 46 | if (!dirsMade) { 47 | dirsMade = true; 48 | if (!cacheFolder.mkdirs()) { 49 | effectManager.onError("Could not create cache folder: " + cacheFolder.getAbsolutePath()); 50 | } 51 | } 52 | 53 | String cacheFileName = URLEncoder.encode(fileName, "UTF-8"); 54 | imageFile = new File(cacheFolder, cacheFileName); 55 | if (!imageFile.exists()) { 56 | URL imageUrl = new URL(fileName); 57 | HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); 58 | conn.setConnectTimeout(REQUEST_TIMEOUT); 59 | conn.setReadTimeout(REQUEST_TIMEOUT); 60 | conn.setInstanceFollowRedirects(true); 61 | InputStream in = conn.getInputStream(); 62 | OutputStream out = new FileOutputStream(imageFile); 63 | byte[] buffer = new byte[BUFFER_SIZE]; 64 | int len; 65 | 66 | while ((len = in.read(buffer)) != -1) { 67 | out.write(buffer, 0, len); 68 | } 69 | out.close(); 70 | } 71 | } catch (Exception ex) { 72 | effectManager.getLogger().log(Level.WARNING, "Failed to load file " + fileName, ex); 73 | callback.loaded(new BufferedImage[0]); 74 | return; 75 | } 76 | } else if (!fileName.startsWith(File.pathSeparator)) { 77 | imageFile = new File(effectManager.getOwningPlugin().getDataFolder(), fileName); 78 | if (!imageFile.exists()) { 79 | imageFile = new File(fileName); 80 | } 81 | } else { 82 | imageFile = new File(fileName); 83 | } 84 | if (!imageFile.exists()) { 85 | effectManager.getLogger().log(Level.WARNING, "Failed to find file " + fileName); 86 | images = new BufferedImage[0]; 87 | callback.loaded(images); 88 | return; 89 | } 90 | try { 91 | if (fileName.endsWith(".gif")) { 92 | ImageReader reader = ImageIO.getImageReadersBySuffix("GIF").next(); 93 | ImageInputStream in = ImageIO.createImageInputStream(imageFile); 94 | reader.setInput(in); 95 | int numImages = reader.getNumImages(true); 96 | images = new BufferedImage[numImages]; 97 | for (int i = 0, count = numImages; i < count; i++) { 98 | images[i] = reader.read(i); 99 | } 100 | } else { 101 | images = new BufferedImage[1]; 102 | images[0] = ImageIO.read(imageFile); 103 | } 104 | } catch (Exception ex) { 105 | effectManager.getLogger().log(Level.WARNING, "Failed to load file " + fileName, ex); 106 | images = new BufferedImage[0]; 107 | } 108 | 109 | callback.loaded(images); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/ParticleDisplay.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import java.util.List; 4 | 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.Color; 7 | import org.bukkit.Location; 8 | import org.bukkit.Material; 9 | import org.bukkit.Particle; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.inventory.ItemStack; 12 | 13 | import de.slikey.effectlib.EffectManager; 14 | import de.slikey.effectlib.util.versions.ParticleDisplay_12; 15 | import de.slikey.effectlib.util.versions.ParticleDisplay_13; 16 | 17 | public abstract class ParticleDisplay { 18 | private EffectManager manager; 19 | 20 | public abstract void display(Particle particle, Location center, float offsetX, float offsetY, float offsetZ, float speed, int amount, float size, Color color, Material material, byte materialData, double range, List targetPlayers); 21 | 22 | protected void display(Particle particle, Location center, float offsetX, float offsetY, float offsetZ, float speed, int amount, Object data, double range, List targetPlayers) { 23 | try { 24 | if (targetPlayers == null) { 25 | double squared = range * range; 26 | for (Player player : Bukkit.getOnlinePlayers()) { 27 | if (player.getWorld() != center.getWorld() || player.getLocation().distanceSquared(center) > squared) { 28 | continue; 29 | } 30 | player.spawnParticle(particle, center, amount, offsetX, offsetY, offsetZ, speed, data); 31 | } 32 | } else { 33 | for (Player player : targetPlayers) { 34 | player.spawnParticle(particle, center, amount, offsetX, offsetY, offsetZ, speed, data); 35 | } 36 | } 37 | } catch (Exception ex) { 38 | if (manager != null) { 39 | manager.onError(ex); 40 | } 41 | } 42 | } 43 | 44 | protected void displayItem(Particle particle, Location center, float offsetX, float offsetY, float offsetZ, float speed, int amount, Material material, byte materialData, double range, List targetPlayers) { 45 | if (material == null || material == Material.AIR) { 46 | return; 47 | } 48 | 49 | ItemStack item = new ItemStack(material); 50 | item.setDurability(materialData); 51 | display(particle, center, offsetX, offsetY, offsetZ, speed, amount, item, range, targetPlayers); 52 | } 53 | 54 | protected void displayLegacyColored(Particle particle, Location center, float speed, Color color, double range, List targetPlayers) { 55 | int amount = 0; 56 | // Colored particles can't have a speed of 0. 57 | if (speed == 0) { 58 | speed = 1; 59 | } 60 | float offsetX = (float) color.getRed() / 255; 61 | float offsetY = (float) color.getGreen() / 255; 62 | float offsetZ = (float) color.getBlue() / 255; 63 | 64 | // The redstone particle reverts to red if R is 0! 65 | if (offsetX < Float.MIN_NORMAL) { 66 | offsetX = Float.MIN_NORMAL; 67 | } 68 | 69 | display(particle, center, offsetX, offsetY, offsetZ, speed, amount, null, range, targetPlayers); 70 | } 71 | 72 | public void setManager(EffectManager manager) { 73 | this.manager = manager; 74 | } 75 | 76 | public static ParticleDisplay newInstance() { 77 | ParticleDisplay display; 78 | try { 79 | Particle.valueOf("SQUID_INK"); 80 | display = new ParticleDisplay_13(); 81 | } catch (Throwable not13) { 82 | display = new ParticleDisplay_12(); 83 | } 84 | return display; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/RandomUtils.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import java.util.Random; 4 | import org.bukkit.Material; 5 | import org.bukkit.util.Vector; 6 | 7 | public final class RandomUtils { 8 | 9 | public static final Random random = new Random(System.nanoTime()); 10 | 11 | private RandomUtils() { 12 | // No instance allowed 13 | } 14 | 15 | public static Vector getRandomVector() { 16 | double x, y, z; 17 | x = random.nextDouble() * 2 - 1; 18 | y = random.nextDouble() * 2 - 1; 19 | z = random.nextDouble() * 2 - 1; 20 | 21 | return new Vector(x, y, z).normalize(); 22 | } 23 | 24 | public static Vector getRandomCircleVector() { 25 | double rnd, x, z; 26 | rnd = random.nextDouble() * 2 * Math.PI; 27 | x = Math.cos(rnd); 28 | z = Math.sin(rnd); 29 | 30 | return new Vector(x, 0, z); 31 | } 32 | 33 | public static Material getRandomMaterial(Material[] materials) { 34 | return materials[random.nextInt(materials.length)]; 35 | } 36 | 37 | public static double getRandomAngle() { 38 | return random.nextDouble() * 2 * Math.PI; 39 | } 40 | 41 | public static boolean checkProbability(double probability) { 42 | return probability >= 1 ? true : random.nextDouble() < probability; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/StringParser.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import java.awt.Color; 4 | import java.awt.Font; 5 | import java.awt.FontMetrics; 6 | import java.awt.Graphics; 7 | import java.awt.font.FontRenderContext; 8 | import java.awt.geom.Rectangle2D; 9 | import java.awt.image.BufferedImage; 10 | 11 | /** 12 | * Based on answer at StackOverflow 13 | * 14 | * @see http://stackoverflow.com/questions/17282495/java-parsing-truetype-font-to-extract-each-characters-as-image-its-code 15 | * @author Kevin 16 | * 17 | */ 18 | public final class StringParser { 19 | 20 | private StringParser() { 21 | 22 | } 23 | 24 | public static BufferedImage stringToBufferedImage(Font font, String s) { 25 | BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR); 26 | Graphics g = img.getGraphics(); 27 | g.setFont(font); 28 | 29 | FontRenderContext frc = g.getFontMetrics().getFontRenderContext(); 30 | Rectangle2D rect = font.getStringBounds(s, frc); 31 | g.dispose(); 32 | 33 | img = new BufferedImage((int) Math.ceil(rect.getWidth()), (int) Math.ceil(rect.getHeight()), BufferedImage.TYPE_4BYTE_ABGR); 34 | g = img.getGraphics(); 35 | g.setColor(Color.black); 36 | g.setFont(font); 37 | 38 | FontMetrics fm = g.getFontMetrics(); 39 | int x = 0; 40 | int y = fm.getAscent(); 41 | 42 | g.drawString(s, x, y); 43 | g.dispose(); 44 | 45 | return img; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/VectorUtils.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.util.Vector; 5 | 6 | public final class VectorUtils { 7 | 8 | private VectorUtils() { 9 | } 10 | 11 | public static final Vector rotateAroundAxisX(Vector v, double angle) { 12 | double y, z, cos, sin; 13 | cos = Math.cos(angle); 14 | sin = Math.sin(angle); 15 | y = v.getY() * cos - v.getZ() * sin; 16 | z = v.getY() * sin + v.getZ() * cos; 17 | return v.setY(y).setZ(z); 18 | } 19 | 20 | public static final Vector rotateAroundAxisY(Vector v, double angle) { 21 | double x, z, cos, sin; 22 | cos = Math.cos(angle); 23 | sin = Math.sin(angle); 24 | x = v.getX() * cos + v.getZ() * sin; 25 | z = v.getX() * -sin + v.getZ() * cos; 26 | return v.setX(x).setZ(z); 27 | } 28 | 29 | public static final Vector rotateAroundAxisZ(Vector v, double angle) { 30 | double x, y, cos, sin; 31 | cos = Math.cos(angle); 32 | sin = Math.sin(angle); 33 | x = v.getX() * cos - v.getY() * sin; 34 | y = v.getX() * sin + v.getY() * cos; 35 | return v.setX(x).setY(y); 36 | } 37 | 38 | public static final Vector rotateVector(Vector v, double angleX, double angleY, double angleZ) { 39 | // double x = v.getX(), y = v.getY(), z = v.getZ(); 40 | // double cosX = Math.cos(angleX), sinX = Math.sin(angleX), cosY = 41 | // Math.cos(angleY), sinY = Math.sin(angleY), cosZ = Math.cos(angleZ), 42 | // sinZ = Math.sin(angleZ); 43 | // double nx, ny, nz; 44 | // nx = (x * cosY + z * sinY) * (x * cosZ - y * sinZ); 45 | // ny = (y * cosX - z * sinX) * (x * sinZ + y * cosZ); 46 | // nz = (y * sinX + z * cosX) * (-x * sinY + z * cosY); 47 | // return v.setX(nx).setY(ny).setZ(nz); 48 | // Having some strange behavior up there.. Have to look in it later. TODO 49 | rotateAroundAxisX(v, angleX); 50 | rotateAroundAxisY(v, angleY); 51 | rotateAroundAxisZ(v, angleZ); 52 | return v; 53 | } 54 | 55 | /** 56 | * Rotate a vector about a location using that location's direction 57 | * 58 | * @param v 59 | * @param location 60 | * @return 61 | */ 62 | public static final Vector rotateVector(Vector v, Location location) { 63 | return rotateVector(v, location.getYaw(), location.getPitch()); 64 | } 65 | 66 | /** 67 | * This handles non-unit vectors, with yaw and pitch instead of X,Y,Z angles. 68 | * 69 | * Thanks to SexyToad! 70 | * 71 | * @param v 72 | * @param yawDegrees 73 | * @param pitchDegrees 74 | * @return 75 | */ 76 | public static final Vector rotateVector(Vector v, float yawDegrees, float pitchDegrees) { 77 | double yaw = Math.toRadians(-1 * (yawDegrees + 90)); 78 | double pitch = Math.toRadians(-pitchDegrees); 79 | 80 | double cosYaw = Math.cos(yaw); 81 | double cosPitch = Math.cos(pitch); 82 | double sinYaw = Math.sin(yaw); 83 | double sinPitch = Math.sin(pitch); 84 | 85 | double initialX, initialY, initialZ; 86 | double x, y, z; 87 | 88 | // Z_Axis rotation (Pitch) 89 | initialX = v.getX(); 90 | initialY = v.getY(); 91 | x = initialX * cosPitch - initialY * sinPitch; 92 | y = initialX * sinPitch + initialY * cosPitch; 93 | 94 | // Y_Axis rotation (Yaw) 95 | initialZ = v.getZ(); 96 | initialX = x; 97 | z = initialZ * cosYaw - initialX * sinYaw; 98 | x = initialZ * sinYaw + initialX * cosYaw; 99 | 100 | return new Vector(x, y, z); 101 | } 102 | 103 | public static final double angleToXAxis(Vector vector) { 104 | return Math.atan2(vector.getX(), vector.getY()); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/versions/ParticleDisplay_12.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util.versions; 2 | 3 | import java.util.List; 4 | 5 | import org.bukkit.Color; 6 | import org.bukkit.Location; 7 | import org.bukkit.Material; 8 | import org.bukkit.Particle; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.material.MaterialData; 11 | 12 | import de.slikey.effectlib.util.ParticleDisplay; 13 | 14 | public class ParticleDisplay_12 extends ParticleDisplay { 15 | @Override 16 | @SuppressWarnings("deprecation") 17 | public void display(Particle particle, Location center, float offsetX, float offsetY, float offsetZ, float speed, int amount, float size, Color color, Material material, byte materialData, double range, List targetPlayers) { 18 | // Legacy colorizeable particles 19 | if (color != null && (particle == Particle.REDSTONE || particle == Particle.SPELL_MOB || particle == Particle.SPELL_MOB_AMBIENT)) { 20 | displayLegacyColored(particle, center, speed, color, range, targetPlayers); 21 | return; 22 | } 23 | 24 | if (particle == Particle.ITEM_CRACK) { 25 | displayItem(particle, center, offsetX, offsetY, offsetZ, speed, amount, material, materialData, range, targetPlayers); 26 | return; 27 | } 28 | 29 | Object data = null; 30 | if (particle == Particle.BLOCK_CRACK || particle == Particle.BLOCK_DUST || particle.name().equals("FALLING_DUST")) { 31 | if (material == null || material == Material.AIR) { 32 | return; 33 | } 34 | data = new MaterialData(material, materialData); 35 | } 36 | 37 | display(particle, center, offsetX, offsetY, offsetZ, speed, amount, data, range, targetPlayers); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/de/slikey/effectlib/util/versions/ParticleDisplay_13.java: -------------------------------------------------------------------------------- 1 | package de.slikey.effectlib.util.versions; 2 | 3 | import java.util.List; 4 | 5 | import org.bukkit.Color; 6 | import org.bukkit.Location; 7 | import org.bukkit.Material; 8 | import org.bukkit.Particle; 9 | import org.bukkit.entity.Player; 10 | 11 | import de.slikey.effectlib.util.ParticleDisplay; 12 | 13 | public class ParticleDisplay_13 extends ParticleDisplay { 14 | @Override 15 | public void display(Particle particle, Location center, float offsetX, float offsetY, float offsetZ, float speed, int amount, float size, Color color, Material material, byte materialData, double range, List targetPlayers) { 16 | // Legacy colorizeable particles 17 | if (color != null && (particle == Particle.SPELL_MOB || particle == Particle.SPELL_MOB_AMBIENT)) { 18 | displayLegacyColored(particle, center, speed, color, range, targetPlayers); 19 | return; 20 | } 21 | 22 | if (particle == Particle.ITEM_CRACK) { 23 | displayItem(particle, center, offsetX, offsetY, offsetZ, speed, amount, material, materialData, range, targetPlayers); 24 | return; 25 | } 26 | 27 | Object data = null; 28 | if (particle == Particle.BLOCK_CRACK || particle == Particle.BLOCK_DUST || particle == Particle.FALLING_DUST) { 29 | if (material == null || material == Material.AIR) { 30 | return; 31 | } 32 | data = material.createBlockData(); 33 | if (data == null) { 34 | return; 35 | } 36 | } 37 | 38 | if (particle == Particle.REDSTONE) { 39 | // color is required for 1.13 40 | if (color == null) { 41 | color = Color.RED; 42 | } 43 | data = new Particle.DustOptions(color, size); 44 | } 45 | 46 | display(particle, center, offsetX, offsetY, offsetZ, speed, amount, data, range, targetPlayers); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/resources/migrate.php: -------------------------------------------------------------------------------- 1 | \n"); 12 | } 13 | 14 | $inputFile = $argv[1]; 15 | $outputFile = $argv[2]; 16 | 17 | $effectTranslation = array( 18 | 'huge_explosion' => 'explosion_huge', 19 | 'large_explode' => 'explosion_large', 20 | 'bubble' => 'water_bubble', 21 | 'suspend' => 'suspended', 22 | 'depth_suspend' => 'suspended_depth', 23 | 'magic_crit' => 'crit_magic', 24 | 'smoke' => 'smoke_normal', 25 | 'mob_spell' => 'spell_mob', 26 | 'mob_spell_ambient' => 'spell_mob_ambient', 27 | 'instant_spell' => 'spell_instant', 28 | 'witch_magic' => 'spell_witch', 29 | 'explode' => 'explosion_normal', 30 | 'splash' => 'water_splash', 31 | 'wake' => 'water_wake', 32 | 'large_smoke' => 'smoke_large', 33 | 'red_dust' => 'redstone', 34 | 'snowball_poof' => 'snowball', 35 | 'angry_villager' => 'villager_angry', 36 | 'happy_villager' => 'villager_happy', 37 | 'droplet' => 'water_drop', 38 | 'take' => 'item_take', 39 | 'icon_crack' => 'item_crack', 40 | 'tile_crack' => 'block_dust', 41 | ); 42 | 43 | $contents = file_get_contents($inputFile); 44 | foreach ($effectTranslation as $from => $to) 45 | { 46 | $contents = str_replace($from, $to, $contents); 47 | } 48 | 49 | file_put_contents($outputFile, $contents); -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: EffectLib 2 | main: de.slikey.effectlib.EffectLib 3 | version: ${project.version} 4 | description: This library supports other plugins to perform cool effects. 5 | author: Slikey 6 | website: http://www.kevin-carstens.de/ 7 | prefix: Effect Library 8 | load: POSTWORLD 9 | database: false 10 | --------------------------------------------------------------------------------