@@ -1,3 +1,12 @@ | |||
VERSION 1.5 | |||
* Make final all classes of the Cosmetic Effects | |||
* Rename 'FIGLET' Cosmetic Effect to 'FIGLET2D' | |||
* Rename 'WALL' Cosmetic Effect to 'SYMBOLS2D' | |||
* Add 'IMAGE2D' Cosmetic Effect | |||
* Remove 'X_ROTATION', 'Y_ROTATION' and 'Z_ROTATION' parameters from 'FIGLET2D' and 'SYMBOLS2D' Cosmetic Effects | |||
* Add 'ROTATION' parameter to 'FIGLET2D' and 'SYMBOLS2D' Cosmetic Effects | |||
* Rename 'DOTS' and 'DOTS_FILE' parameters in 'SYMBOLS2D' Cosmetic Effect to 'SYMBOLS' and 'SYMBOLS_FILE' accordingly | |||
VERSION 1.4.1 | |||
* Update to GWMLibrary 2.5.1 | |||
* Update to banana 1.2.1 | |||
@@ -6,7 +6,7 @@ | |||
<groupId>dev.gwm.spongeplugin</groupId> | |||
<artifactId>cosmetics</artifactId> | |||
<version>1.4.1</version> | |||
<version>1.5</version> | |||
<name>Cosmetics</name> | |||
<packaging>jar</packaging> | |||
@@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger; | |||
@Plugin(id = "cosmetics", | |||
name = "Cosmetics", | |||
version = "1.4.1", | |||
version = "1.5", | |||
description = "Fancy cosmetic effects", | |||
authors = {"GWM"/* My contacts: | |||
* E-Mail(nazark@tutanota.com), | |||
@@ -43,7 +43,7 @@ import java.util.concurrent.atomic.AtomicInteger; | |||
}) | |||
public class Cosmetics extends SpongePlugin { | |||
public static final Version VERSION = new Version(null, 1, 4, 1); | |||
public static final Version VERSION = new Version(null, 1, 5); | |||
private static Cosmetics instance = null; | |||
@@ -127,10 +127,12 @@ public class Cosmetics extends SpongePlugin { | |||
HelixCosmeticEffect.class); | |||
event.register(new SuperObjectIdentifier<>(CosmeticsSuperObjectCategories.COSMETIC_EFFECT, CircleCosmeticEffect.TYPE), | |||
CircleCosmeticEffect.class); | |||
event.register(new SuperObjectIdentifier<>(CosmeticsSuperObjectCategories.COSMETIC_EFFECT, WallCosmeticEffects.TYPE), | |||
WallCosmeticEffects.class); | |||
event.register(new SuperObjectIdentifier<>(CosmeticsSuperObjectCategories.COSMETIC_EFFECT, FigletCosmeticEffect.TYPE), | |||
FigletCosmeticEffect.class); | |||
event.register(new SuperObjectIdentifier<>(CosmeticsSuperObjectCategories.COSMETIC_EFFECT, Symbols2dCosmeticEffects.TYPE), | |||
Symbols2dCosmeticEffects.class); | |||
event.register(new SuperObjectIdentifier<>(CosmeticsSuperObjectCategories.COSMETIC_EFFECT, Figlet2dCosmeticEffect.TYPE), | |||
Figlet2dCosmeticEffect.class); | |||
event.register(new SuperObjectIdentifier<>(CosmeticsSuperObjectCategories.COSMETIC_EFFECT, Image2dCosmeticEffect.TYPE), | |||
Image2dCosmeticEffect.class); | |||
} | |||
@Listener | |||
@@ -11,7 +11,7 @@ import org.spongepowered.api.world.Locatable; | |||
import java.util.Optional; | |||
public class BlockHighlightCosmeticEffect extends BaseCosmeticEffect { | |||
public final class BlockHighlightCosmeticEffect extends BaseCosmeticEffect { | |||
public static final String TYPE = "BLOCK-HIGHLIGHT"; | |||
@@ -12,7 +12,7 @@ import org.spongepowered.api.world.Locatable; | |||
import java.util.Optional; | |||
public class CircleCosmeticEffect extends BaseCosmeticEffect { | |||
public final class CircleCosmeticEffect extends BaseCosmeticEffect { | |||
public static final String TYPE = "CIRCLE"; | |||
@@ -0,0 +1,137 @@ | |||
package dev.gwm.spongeplugin.cosmetics.superobject.effect; | |||
import com.flowpowered.math.vector.Vector3d; | |||
import com.google.common.reflect.TypeToken; | |||
import dev.gwm.spongeplugin.cosmetics.superobject.effect.base.Abstract2dCosmeticEffect; | |||
import dev.gwm.spongeplugin.library.exception.SuperObjectConstructionException; | |||
import dev.gwm.spongeplugin.library.utils.GWMLibraryUtils; | |||
import io.leego.banana.BananaUtils; | |||
import ninja.leaping.configurate.ConfigurationNode; | |||
import org.spongepowered.api.effect.particle.ParticleEffect; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
public final class Figlet2dCosmeticEffect extends Abstract2dCosmeticEffect { | |||
public static final String TYPE = "FIGLET2D"; | |||
private final Vector3d rotation; | |||
private final List<String> text; | |||
private final String font; | |||
private final double horizontalParticleDistance; | |||
private final double verticalParticleDistance; | |||
private final Map<Vector3d, ParticleEffect> dots; | |||
public Figlet2dCosmeticEffect(ConfigurationNode node) { | |||
super(node); | |||
try { | |||
ConfigurationNode rotationNode = node.getNode("ROTATION"); | |||
ConfigurationNode textNode = node.getNode("TEXT"); | |||
ConfigurationNode textFileNode = node.getNode("TEXT_FILE"); | |||
ConfigurationNode fontNode = node.getNode("FONT"); | |||
ConfigurationNode horizontalParticleDistanceNode = node.getNode("HORIZONTAL_PARTICLE_DISTANCE"); | |||
ConfigurationNode verticalParticleDistanceNode = node.getNode("VERTICAL_PARTICLE_DISTANCE"); | |||
if (!rotationNode.isVirtual()) { | |||
rotation = GWMLibraryUtils.parseVector3d(rotationNode); | |||
} else { | |||
rotation = Vector3d.ZERO; | |||
} | |||
if (!textNode.isVirtual()) { | |||
text = textNode.getList(TypeToken.of(String.class)); | |||
} else if (!textFileNode.isVirtual()) { | |||
text = new BufferedReader(new FileReader(new File(textFileNode.getString()))). | |||
lines(). | |||
collect(Collectors.toList()); | |||
} else { | |||
throw new IllegalArgumentException("Both TEXT and TEXT_FILE nodes do not exist!"); | |||
} | |||
font = fontNode.getString("Banner"); | |||
horizontalParticleDistance = horizontalParticleDistanceNode.getDouble(0.2); | |||
if (horizontalParticleDistance < 0 || horizontalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
verticalParticleDistance = verticalParticleDistanceNode.getDouble(0.4); | |||
if (verticalParticleDistance < 0 || verticalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
dots = convertToDots(text, font); | |||
} catch (Exception e) { | |||
throw new SuperObjectConstructionException(category(), type(), e); | |||
} | |||
} | |||
public Figlet2dCosmeticEffect(String id, | |||
Optional<Long> delay, Optional<Vector3d> offset, | |||
ParticleEffect particleEffect, boolean perAnimationColor, boolean perParticleColor, | |||
Vector3d rotation, | |||
List<String> text, String font, | |||
double horizontalParticleDistance, double verticalParticleDistance) { | |||
super(id, delay, offset, particleEffect, perAnimationColor, perParticleColor); | |||
this.rotation = rotation; | |||
this.text = text; | |||
this.font = font; | |||
if (horizontalParticleDistance <= 0) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is equal to or less than 0!"); | |||
} | |||
this.horizontalParticleDistance = horizontalParticleDistance; | |||
if (verticalParticleDistance <= 0 ) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is equal to or less than 0!"); | |||
} | |||
this.verticalParticleDistance = verticalParticleDistance; | |||
dots = convertToDots(text, font); | |||
} | |||
private Map<Vector3d, ParticleEffect> convertToDots(List<String> text, String font) { | |||
try { | |||
String[] splited = BananaUtils.bananaify(GWMLibraryUtils.joinString(text), font).split("\n"); | |||
Map<Vector3d, ParticleEffect> dots = new HashMap<>(); | |||
for (int y = 0; y < splited.length; y++) { | |||
String string = splited[y]; | |||
for (int x = 0; x < string.length(); x++) { | |||
if (string.charAt(x) != ' ') { | |||
dots.put(new Vector3d(x * getVerticalParticleDistance(), -y * getHorizontalParticleDistance(), 0), getParticleEffect()); | |||
} | |||
} | |||
} | |||
return dots; | |||
} catch (Exception e) { | |||
throw new RuntimeException("Failed to convert text", e); | |||
} | |||
} | |||
@Override | |||
public String type() { | |||
return TYPE; | |||
} | |||
@Override | |||
public Vector3d getRotation() { | |||
return rotation; | |||
} | |||
@Override | |||
public Map<Vector3d, ParticleEffect> getDots() { | |||
return colorDots(Collections.unmodifiableMap(dots)); | |||
} | |||
public List<String> getText() { | |||
return text; | |||
} | |||
public String getFont() { | |||
return font; | |||
} | |||
public double getHorizontalParticleDistance() { | |||
return horizontalParticleDistance; | |||
} | |||
public double getVerticalParticleDistance() { | |||
return verticalParticleDistance; | |||
} | |||
} |
@@ -1,198 +0,0 @@ | |||
package dev.gwm.spongeplugin.cosmetics.superobject.effect; | |||
import com.flowpowered.math.vector.Vector3d; | |||
import com.google.common.reflect.TypeToken; | |||
import dev.gwm.spongeplugin.cosmetics.superobject.effect.base.Abstract2dCosmeticEffect; | |||
import dev.gwm.spongeplugin.library.exception.SuperObjectConstructionException; | |||
import dev.gwm.spongeplugin.library.utils.GWMLibraryUtils; | |||
import io.leego.banana.BananaUtils; | |||
import ninja.leaping.configurate.ConfigurationNode; | |||
import org.spongepowered.api.effect.particle.ParticleEffect; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.stream.Collectors; | |||
public class FigletCosmeticEffect extends Abstract2dCosmeticEffect { | |||
public static final String TYPE = "FIGLET"; | |||
private final List<String> text; | |||
private final String font; | |||
private final boolean[][] dots; | |||
private final double horizontalParticleDistance; | |||
private final double verticalParticleDistance; | |||
private final double x1Multiplier; | |||
private final double x2Multiplier; | |||
private final double y1Multiplier; | |||
private final double y2Multiplier; | |||
private final double z1Multiplier; | |||
private final double z2Multiplier; | |||
public FigletCosmeticEffect(ConfigurationNode node) { | |||
super(node); | |||
try { | |||
ConfigurationNode textNode = node.getNode("TEXT"); | |||
ConfigurationNode textFileNode = node.getNode("TEXT_FILE"); | |||
ConfigurationNode fontNode = node.getNode("FONT"); | |||
ConfigurationNode horizontalParticleDistanceNode = node.getNode("HORIZONTAL_PARTICLE_DISTANCE"); | |||
ConfigurationNode verticalParticleDistanceNode = node.getNode("VERTICAL_PARTICLE_DISTANCE"); | |||
ConfigurationNode xAngleNode = node.getNode("X_ROTATION"); | |||
ConfigurationNode yAngleNode = node.getNode("Y_ROTATION"); | |||
ConfigurationNode zAngleNode = node.getNode("Z_ROTATION"); | |||
if (!textNode.isVirtual()) { | |||
text = textNode.getList(TypeToken.of(String.class)); | |||
} else if (!textFileNode.isVirtual()) { | |||
text = new BufferedReader(new FileReader(new File(textFileNode.getString()))). | |||
lines(). | |||
collect(Collectors.toList()); | |||
} else { | |||
throw new IllegalArgumentException("Both TEXT and TEXT_FILE node do not exist!"); | |||
} | |||
font = fontNode.getString("Banner"); | |||
dots = convert(text, font); | |||
horizontalParticleDistance = horizontalParticleDistanceNode.getDouble(0.2); | |||
if (horizontalParticleDistance < 0 || horizontalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
verticalParticleDistance = verticalParticleDistanceNode.getDouble(0.4); | |||
if (verticalParticleDistance < 0 || verticalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
double xAngle = xAngleNode.getDouble(0); | |||
if (xAngle < 0 || xAngle >= 360) { | |||
throw new IllegalArgumentException("X Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
x1Multiplier = Math.cos(Math.toRadians(xAngle)); | |||
x2Multiplier = Math.sin(Math.toRadians(xAngle)); | |||
double yAngle = yAngleNode.getDouble(0); | |||
if (yAngle < 0 || yAngle >= 360) { | |||
throw new IllegalArgumentException("Y Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
y1Multiplier = Math.cos(Math.toRadians(yAngle)); | |||
y2Multiplier = Math.sin(Math.toRadians(yAngle)); | |||
double zAngle = zAngleNode.getDouble(0); | |||
if (zAngle < 0 || zAngle >= 360) { | |||
throw new IllegalArgumentException("Z Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
z1Multiplier = Math.cos(Math.toRadians(zAngle)); | |||
z2Multiplier = Math.sin(Math.toRadians(zAngle)); | |||
} catch (Exception e) { | |||
throw new SuperObjectConstructionException(category(), type(), e); | |||
} | |||
} | |||
public FigletCosmeticEffect(String id, | |||
Optional<Long> delay, Optional<Vector3d> offset, | |||
ParticleEffect particleEffect, boolean perAnimationColor, boolean perParticleColor, | |||
List<String> text, String font, | |||
double horizontalParticleDistance, double verticalParticleDistance, | |||
double xAngle, double yAngle, double zAngle) { | |||
super(id, delay, offset, particleEffect, perAnimationColor, perParticleColor); | |||
this.text = text; | |||
this.font = font; | |||
dots = convert(text, font); | |||
if (horizontalParticleDistance <= 0) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is equal to or less than 0!"); | |||
} | |||
this.horizontalParticleDistance = horizontalParticleDistance; | |||
if (verticalParticleDistance <= 0 ) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is equal to or less than 0!"); | |||
} | |||
this.verticalParticleDistance = verticalParticleDistance; | |||
if (xAngle < 0 || xAngle >= 360) { | |||
throw new IllegalArgumentException("X Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
x1Multiplier = Math.cos(Math.toRadians(xAngle)); | |||
x2Multiplier = Math.sin(Math.toRadians(xAngle)); | |||
if (yAngle < 0 || yAngle >= 360) { | |||
throw new IllegalArgumentException("Y Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
y1Multiplier = Math.cos(Math.toRadians(yAngle)); | |||
y2Multiplier = Math.sin(Math.toRadians(yAngle)); | |||
if (zAngle < 0 || zAngle >= 360) { | |||
throw new IllegalArgumentException("Z Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
z1Multiplier = Math.cos(Math.toRadians(zAngle)); | |||
z2Multiplier = Math.sin(Math.toRadians(zAngle)); | |||
} | |||
private boolean[][] convert(List<String> text, String font) { | |||
try { | |||
String[] splited = BananaUtils.bananaify(GWMLibraryUtils.joinString(text), font).split("\n"); | |||
boolean[][] dots = new boolean[splited.length][]; | |||
for (int i = splited.length - 1; i >= 0; i--) { | |||
String string = splited[i]; | |||
boolean[] array = new boolean[string.length()]; | |||
for (int j = 0; j < string.length(); j++) { | |||
array[j] = string.charAt(j) != ' '; | |||
} | |||
dots[splited.length - 1 - i] = array; | |||
} | |||
return dots; | |||
} catch (Exception e) { | |||
throw new RuntimeException("Failed to convert text", e); | |||
} | |||
} | |||
@Override | |||
public String type() { | |||
return TYPE; | |||
} | |||
public List<String> getText() { | |||
return text; | |||
} | |||
public String getFont() { | |||
return font; | |||
} | |||
@Override | |||
public boolean[][] getDots() { | |||
return dots; | |||
} | |||
@Override | |||
public double getHorizontalParticleDistance() { | |||
return horizontalParticleDistance; | |||
} | |||
@Override | |||
public double getVerticalParticleDistance() { | |||
return verticalParticleDistance; | |||
} | |||
@Override | |||
public double getX1Multiplier() { | |||
return x1Multiplier; | |||
} | |||
@Override | |||
public double getX2Multiplier() { | |||
return x2Multiplier; | |||
} | |||
@Override | |||
public double getY1Multiplier() { | |||
return y1Multiplier; | |||
} | |||
@Override | |||
public double getY2Multiplier() { | |||
return y2Multiplier; | |||
} | |||
@Override | |||
public double getZ1Multiplier() { | |||
return z1Multiplier; | |||
} | |||
@Override | |||
public double getZ2Multiplier() { | |||
return z2Multiplier; | |||
} | |||
} |
@@ -11,7 +11,7 @@ import org.spongepowered.api.world.Locatable; | |||
import java.util.Optional; | |||
public class HelixCosmeticEffect extends BaseCosmeticEffect { | |||
public final class HelixCosmeticEffect extends BaseCosmeticEffect { | |||
public static final String TYPE = "HELIX"; | |||
@@ -0,0 +1,129 @@ | |||
package dev.gwm.spongeplugin.cosmetics.superobject.effect; | |||
import com.flowpowered.math.vector.Vector3d; | |||
import dev.gwm.spongeplugin.cosmetics.superobject.effect.base.Abstract2dCosmeticEffect; | |||
import dev.gwm.spongeplugin.library.exception.SuperObjectConstructionException; | |||
import dev.gwm.spongeplugin.library.utils.GWMLibraryUtils; | |||
import ninja.leaping.configurate.ConfigurationNode; | |||
import org.spongepowered.api.effect.particle.ParticleEffect; | |||
import org.spongepowered.api.effect.particle.ParticleOptions; | |||
import org.spongepowered.api.util.Color; | |||
import javax.imageio.ImageIO; | |||
import java.awt.image.BufferedImage; | |||
import java.io.File; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
public final class Image2dCosmeticEffect extends Abstract2dCosmeticEffect { | |||
public static final String TYPE = "IMAGE2D"; | |||
private final Vector3d rotation; | |||
private final BufferedImage image; | |||
private final double horizontalParticleDistance; | |||
private final double verticalParticleDistance; | |||
private final Map<Vector3d, ParticleEffect> dots; | |||
public Image2dCosmeticEffect(ConfigurationNode node) { | |||
super(node); | |||
try { | |||
ConfigurationNode rotationNode = node.getNode("ROTATION"); | |||
ConfigurationNode imageFileNode = node.getNode("IMAGE_FILE"); | |||
ConfigurationNode horizontalParticleDistanceNode = node.getNode("HORIZONTAL_PARTICLE_DISTANCE"); | |||
ConfigurationNode verticalParticleDistanceNode = node.getNode("VERTICAL_PARTICLE_DISTANCE"); | |||
if (imageFileNode.isVirtual()) { | |||
throw new IllegalArgumentException("IMAGE node does not exist!"); | |||
} | |||
if (!rotationNode.isVirtual()) { | |||
rotation = GWMLibraryUtils.parseVector3d(rotationNode); | |||
} else { | |||
rotation = Vector3d.ZERO; | |||
} | |||
image = ImageIO.read(new File(imageFileNode.getString())); | |||
horizontalParticleDistance = horizontalParticleDistanceNode.getDouble(0.2); | |||
if (horizontalParticleDistance < 0 || horizontalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
verticalParticleDistance = verticalParticleDistanceNode.getDouble(0.4); | |||
if (verticalParticleDistance < 0 || verticalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
dots = convertToDots(image); | |||
} catch (Exception e) { | |||
throw new SuperObjectConstructionException(category(), type(), e); | |||
} | |||
} | |||
public Image2dCosmeticEffect(String id, | |||
Optional<Long> delay, Optional<Vector3d> offset, | |||
ParticleEffect particleEffect, boolean perAnimationColor, boolean perParticleColor, | |||
Vector3d rotation, | |||
BufferedImage image, | |||
double horizontalParticleDistance, double verticalParticleDistance) { | |||
super(id, delay, offset, particleEffect, perAnimationColor, perParticleColor); | |||
this.rotation = rotation; | |||
this.image = image; | |||
if (horizontalParticleDistance <= 0) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is equal to or less than 0!"); | |||
} | |||
this.horizontalParticleDistance = horizontalParticleDistance; | |||
if (verticalParticleDistance <= 0 ) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is equal to or less than 0!"); | |||
} | |||
this.verticalParticleDistance = verticalParticleDistance; | |||
dots = convertToDots(image); | |||
} | |||
private Map<Vector3d, ParticleEffect> convertToDots(BufferedImage image) { | |||
try { | |||
Map<Vector3d, ParticleEffect> dots = new HashMap<>(); | |||
int height = image.getHeight(); | |||
int width = image.getWidth(); | |||
for (int y = 0; y < height; y++) { | |||
for (int x = 0; x < width; x++) { | |||
java.awt.Color pixelColor = new java.awt.Color(image.getRGB(x, y), true); | |||
if (pixelColor.getAlpha() != 0) { | |||
dots.put(new Vector3d(x * getVerticalParticleDistance(), -y * getHorizontalParticleDistance(), 0), | |||
ParticleEffect.builder(). | |||
from(getParticleEffect()). | |||
option(ParticleOptions.COLOR, Color.of(pixelColor)). | |||
build()); | |||
} | |||
} | |||
} | |||
return dots; | |||
} catch (Exception e) { | |||
throw new RuntimeException("Failed to convert image", e); | |||
} | |||
} | |||
@Override | |||
public String type() { | |||
return TYPE; | |||
} | |||
@Override | |||
public Vector3d getRotation() { | |||
return rotation; | |||
} | |||
@Override | |||
public Map<Vector3d, ParticleEffect> getDots() { | |||
return dots; | |||
} | |||
public BufferedImage getImage() { | |||
return image; | |||
} | |||
public double getHorizontalParticleDistance() { | |||
return horizontalParticleDistance; | |||
} | |||
public double getVerticalParticleDistance() { | |||
return verticalParticleDistance; | |||
} | |||
} |
@@ -0,0 +1,126 @@ | |||
package dev.gwm.spongeplugin.cosmetics.superobject.effect; | |||
import com.flowpowered.math.vector.Vector3d; | |||
import com.google.common.reflect.TypeToken; | |||
import dev.gwm.spongeplugin.cosmetics.superobject.effect.base.Abstract2dCosmeticEffect; | |||
import dev.gwm.spongeplugin.library.exception.SuperObjectConstructionException; | |||
import dev.gwm.spongeplugin.library.utils.GWMLibraryUtils; | |||
import ninja.leaping.configurate.ConfigurationNode; | |||
import org.spongepowered.api.effect.particle.ParticleEffect; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
public final class Symbols2dCosmeticEffects extends Abstract2dCosmeticEffect { | |||
public static final String TYPE = "SYMBOLS2D"; | |||
private final Vector3d rotation; | |||
private final List<String> symbols; | |||
private final double horizontalParticleDistance; | |||
private final double verticalParticleDistance; | |||
private final Map<Vector3d, ParticleEffect> dots; | |||
public Symbols2dCosmeticEffects(ConfigurationNode node) { | |||
super(node); | |||
try { | |||
ConfigurationNode rotationNode = node.getNode("ROTATION"); | |||
ConfigurationNode symbolsNode = node.getNode("SYMBOLS"); | |||
ConfigurationNode symbolsFileNode = node.getNode("SYMBOLS_FILE"); | |||
ConfigurationNode horizontalParticleDistanceNode = node.getNode("HORIZONTAL_PARTICLE_DISTANCE"); | |||
ConfigurationNode verticalParticleDistanceNode = node.getNode("VERTICAL_PARTICLE_DISTANCE"); | |||
if (!rotationNode.isVirtual()) { | |||
rotation = GWMLibraryUtils.parseVector3d(rotationNode); | |||
} else { | |||
rotation = Vector3d.ZERO; | |||
} | |||
if (!symbolsNode.isVirtual()) { | |||
symbols = symbolsNode.getList(TypeToken.of(String.class)); | |||
} else if (!symbolsFileNode.isVirtual()) { | |||
symbols = new BufferedReader(new FileReader(new File(symbolsFileNode.getString()))). | |||
lines(). | |||
collect(Collectors.toList()); | |||
} else { | |||
throw new IllegalArgumentException("Both DOTS and DOTS_FILES nodes do not exist!"); | |||
} | |||
horizontalParticleDistance = horizontalParticleDistanceNode.getDouble(0.2); | |||
if (horizontalParticleDistance < 0 || horizontalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
verticalParticleDistance = verticalParticleDistanceNode.getDouble(0.4); | |||
if (verticalParticleDistance < 0 || verticalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
dots = convertToDots(symbols); | |||
} catch (Exception e) { | |||
throw new SuperObjectConstructionException(category(), type(), e); | |||
} | |||
} | |||
public Symbols2dCosmeticEffects(String id, | |||
Optional<Long> delay, Optional<Vector3d> offset, | |||
ParticleEffect particleEffect, boolean perAnimationColor, boolean perParticleColor, | |||
Vector3d rotation, | |||
List<String> symbols, double horizontalParticleDistance, double verticalParticleDistance) { | |||
super(id, delay, offset, particleEffect, perAnimationColor, perParticleColor); | |||
this.rotation = rotation; | |||
this.symbols = symbols; | |||
if (horizontalParticleDistance <= 0) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is equal to or less than 0!"); | |||
} | |||
this.horizontalParticleDistance = horizontalParticleDistance; | |||
if (verticalParticleDistance <= 0 ) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is equal to or less than 0!"); | |||
} | |||
this.verticalParticleDistance = verticalParticleDistance; | |||
dots = convertToDots(symbols); | |||
} | |||
private Map<Vector3d, ParticleEffect> convertToDots(List<String> symbols) { | |||
try { | |||
Map<Vector3d, ParticleEffect> dots = new HashMap<>(); | |||
for (int y = 0; y < symbols.size(); y++) { | |||
String string = symbols.get(y); | |||
for (int x = 0; x < string.length(); x++) { | |||
if (string.charAt(x) != ' ') { | |||
dots.put(new Vector3d(x * getVerticalParticleDistance(), -y * getHorizontalParticleDistance(), 0), getParticleEffect()); | |||
} | |||
} | |||
} | |||
return dots; | |||
} catch (Exception e) { | |||
throw new RuntimeException("Failed to convert symbols", e); | |||
} | |||
} | |||
@Override | |||
public String type() { | |||
return TYPE; | |||
} | |||
@Override | |||
public Vector3d getRotation() { | |||
return rotation; | |||
} | |||
@Override | |||
public Map<Vector3d, ParticleEffect> getDots() { | |||
return colorDots(Collections.unmodifiableMap(dots)); | |||
} | |||
public List<String> getSymbols() { | |||
return symbols; | |||
} | |||
public double getHorizontalParticleDistance() { | |||
return horizontalParticleDistance; | |||
} | |||
public double getVerticalParticleDistance() { | |||
return verticalParticleDistance; | |||
} | |||
} |
@@ -1,172 +0,0 @@ | |||
package dev.gwm.spongeplugin.cosmetics.superobject.effect; | |||
import com.flowpowered.math.vector.Vector3d; | |||
import com.google.common.reflect.TypeToken; | |||
import dev.gwm.spongeplugin.cosmetics.superobject.effect.base.Abstract2dCosmeticEffect; | |||
import dev.gwm.spongeplugin.library.exception.SuperObjectConstructionException; | |||
import ninja.leaping.configurate.ConfigurationNode; | |||
import org.spongepowered.api.effect.particle.ParticleEffect; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.stream.Collectors; | |||
public class WallCosmeticEffects extends Abstract2dCosmeticEffect { | |||
public static final String TYPE = "WALL"; | |||
private final boolean[][] dots; | |||
private final double horizontalParticleDistance; | |||
private final double verticalParticleDistance; | |||
private final double x1Multiplier; | |||
private final double x2Multiplier; | |||
private final double y1Multiplier; | |||
private final double y2Multiplier; | |||
private final double z1Multiplier; | |||
private final double z2Multiplier; | |||
public WallCosmeticEffects(ConfigurationNode node) { | |||
super(node); | |||
try { | |||
ConfigurationNode dotsNode = node.getNode("DOTS"); | |||
ConfigurationNode dotsFileNode = node.getNode("DOTS_FILE"); | |||
ConfigurationNode horizontalParticleDistanceNode = node.getNode("HORIZONTAL_PARTICLE_DISTANCE"); | |||
ConfigurationNode verticalParticleDistanceNode = node.getNode("VERTICAL_PARTICLE_DISTANCE"); | |||
ConfigurationNode xAngleNode = node.getNode("X_ROTATION"); | |||
ConfigurationNode yAngleNode = node.getNode("Y_ROTATION"); | |||
ConfigurationNode zAngleNode = node.getNode("Z_ROTATION"); | |||
List<String> dotsLines; | |||
if (!dotsNode.isVirtual()) { | |||
dotsLines = dotsNode.getList(TypeToken.of(String.class)); | |||
} else if (!dotsFileNode.isVirtual()) { | |||
dotsLines = new BufferedReader(new FileReader(new File(dotsFileNode.getString()))). | |||
lines(). | |||
collect(Collectors.toList()); | |||
} else { | |||
throw new IllegalArgumentException("Both DOTS and DOTS_FILES node do not exist!"); | |||
} | |||
dots = new boolean[dotsLines.size()][]; | |||
for (int i = dotsLines.size() - 1; i >= 0; i--) { | |||
String dotLine = dotsLines.get(i); | |||
boolean[] array = new boolean[dotLine.length()]; | |||
for (int j = 0; j < dotLine.length(); j++) { | |||
array[j] = dotLine.charAt(j) != ' '; | |||
} | |||
dots[dotsLines.size() - 1 - i] = array; | |||
} | |||
horizontalParticleDistance = horizontalParticleDistanceNode.getDouble(0.2); | |||
if (horizontalParticleDistance < 0 || horizontalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
verticalParticleDistance = verticalParticleDistanceNode.getDouble(0.4); | |||
if (verticalParticleDistance < 0 || verticalParticleDistance >= 360) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is either equal to or greater than 360 or less than 0!"); | |||
} | |||
double xAngle = xAngleNode.getDouble(0); | |||
if (xAngle < 0 || xAngle >= 360) { | |||
throw new IllegalArgumentException("X Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
x1Multiplier = Math.cos(Math.toRadians(xAngle)); | |||
x2Multiplier = Math.sin(Math.toRadians(xAngle)); | |||
double yAngle = yAngleNode.getDouble(0); | |||
if (yAngle < 0 || yAngle >= 360) { | |||
throw new IllegalArgumentException("Y Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
y1Multiplier = Math.cos(Math.toRadians(yAngle)); | |||
y2Multiplier = Math.sin(Math.toRadians(yAngle)); | |||
double zAngle = zAngleNode.getDouble(0); | |||
if (zAngle < 0 || zAngle >= 360) { | |||
throw new IllegalArgumentException("Z Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
z1Multiplier = Math.cos(Math.toRadians(zAngle)); | |||
z2Multiplier = Math.sin(Math.toRadians(zAngle)); | |||
} catch (Exception e) { | |||
throw new SuperObjectConstructionException(category(), type(), e); | |||
} | |||
} | |||
public WallCosmeticEffects(String id, | |||
Optional<Long> delay, Optional<Vector3d> offset, | |||
ParticleEffect particleEffect, boolean perAnimationColor, boolean perParticleColor, | |||
boolean[][] dots, double horizontalParticleDistance, double verticalParticleDistance, | |||
double xAngle, double yAngle, double zAngle) { | |||
super(id, delay, offset, particleEffect, perAnimationColor, perParticleColor); | |||
this.dots = dots; | |||
if (horizontalParticleDistance <= 0) { | |||
throw new IllegalArgumentException("Horizontal Particle Distance is equal to or less than 0!"); | |||
} | |||
this.horizontalParticleDistance = horizontalParticleDistance; | |||
if (verticalParticleDistance <= 0 ) { | |||
throw new IllegalArgumentException("Vertical Particle Distance is equal to or less than 0!"); | |||
} | |||
this.verticalParticleDistance = verticalParticleDistance; | |||
if (xAngle < 0 || xAngle >= 360) { | |||
throw new IllegalArgumentException("X Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
x1Multiplier = Math.cos(Math.toRadians(xAngle)); | |||
x2Multiplier = Math.sin(Math.toRadians(xAngle)); | |||
if (yAngle < 0 || yAngle >= 360) { | |||
throw new IllegalArgumentException("Y Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
y1Multiplier = Math.cos(Math.toRadians(yAngle)); | |||
y2Multiplier = Math.sin(Math.toRadians(yAngle)); | |||
if (zAngle < 0 || zAngle >= 360) { | |||
throw new IllegalArgumentException("Z Angle is either equal to or greater than 360 or less than 0!"); | |||
} | |||
z1Multiplier = Math.cos(Math.toRadians(zAngle)); | |||
z2Multiplier = Math.sin(Math.toRadians(zAngle)); | |||
} | |||
@Override | |||
public String type() { | |||
return TYPE; | |||
} | |||
@Override | |||
protected boolean[][] getDots() { | |||
return dots; | |||
} | |||
@Override | |||
protected double getHorizontalParticleDistance() { | |||
return horizontalParticleDistance; | |||
} | |||
@Override | |||
protected double getVerticalParticleDistance() { | |||
return verticalParticleDistance; | |||
} | |||
@Override | |||
protected double getX1Multiplier() { | |||
return x1Multiplier; | |||
} | |||
@Override | |||
protected double getX2Multiplier() { | |||
return x2Multiplier; | |||
} | |||
@Override | |||
protected double getY1Multiplier() { | |||
return y1Multiplier; | |||
} | |||
@Override | |||
protected double getY2Multiplier() { | |||
return y2Multiplier; | |||
} | |||
@Override | |||
protected double getZ1Multiplier() { | |||
return z1Multiplier; | |||
} | |||
@Override | |||
protected double getZ2Multiplier() { | |||
return z2Multiplier; | |||
} | |||
} |
@@ -1,14 +1,15 @@ | |||
package dev.gwm.spongeplugin.cosmetics.superobject.effect.base; | |||
import com.flowpowered.math.vector.Vector3d; | |||
import dev.gwm.spongeplugin.cosmetics.utils.CosmeticsUtils; | |||
import ninja.leaping.configurate.ConfigurationNode; | |||
import org.spongepowered.api.effect.Viewer; | |||
import org.spongepowered.api.effect.particle.ParticleEffect; | |||
import org.spongepowered.api.effect.particle.ParticleOptions; | |||
import org.spongepowered.api.world.Locatable; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import java.util.function.Function; | |||
import java.util.stream.Collectors; | |||
public abstract class Abstract2dCosmeticEffect extends BaseCosmeticEffect { | |||
@@ -26,57 +27,60 @@ public abstract class Abstract2dCosmeticEffect extends BaseCosmeticEffect { | |||
return new DotsEffectRunnable(viewer, locatable, offset); | |||
} | |||
protected abstract boolean[][] getDots(); | |||
protected abstract double getHorizontalParticleDistance(); | |||
protected abstract double getVerticalParticleDistance(); | |||
protected abstract double getX1Multiplier(); | |||
protected abstract double getX2Multiplier(); | |||
protected abstract double getY1Multiplier(); | |||
protected abstract double getY2Multiplier(); | |||
protected Map<Vector3d, ParticleEffect> colorDots(Map<Vector3d, ParticleEffect> dots) { | |||
if (isPerParticleColor()) { | |||
return dots.keySet(). | |||
stream(). | |||
collect(Collectors.toMap(Function.identity(),it -> getColoredParticleEffect())); | |||
} else if (isPerAnimationColor()){ | |||
ParticleEffect particleEffect = getColoredParticleEffect(); | |||
return dots.keySet(). | |||
stream(). | |||
collect(Collectors.toMap(Function.identity(), it -> particleEffect)); | |||
} else { | |||
return dots; | |||
} | |||
} | |||
protected abstract double getZ1Multiplier(); | |||
protected abstract Map<Vector3d, ParticleEffect> getDots(); | |||
protected abstract double getZ2Multiplier(); | |||
protected abstract Vector3d getRotation(); | |||
protected class DotsEffectRunnable extends AbstractEffectRunnable { | |||
//https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Euler_angles_.28_z-y.E2.80.99-x.E2.80.B3_intrinsic.29_.E2.86.92_Rotation_matrix | |||
private Vector3d rotate(Vector3d vector, Double xDegrees, Double yDegrees, Double zDegrees) { | |||
double cosX = Math.cos(Math.toRadians(xDegrees)); | |||
double sinX = Math.sin(Math.toRadians(xDegrees)); | |||
double cosY = Math.cos(Math.toRadians(yDegrees)); | |||
double sinY = Math.sin(Math.toRadians(yDegrees)); | |||
double cosZ = Math.cos(Math.toRadians(zDegrees)); | |||
double sinZ = Math.sin(Math.toRadians(zDegrees)); | |||
double x = vector.getX() * (cosY * cosZ) + | |||
vector.getY() * (-cosX * sinZ + sinX * sinY * cosZ) + | |||
vector.getZ() * (sinX * sinZ + cosX * sinY * cosZ); | |||
double y = vector.getX() * (cosY * sinZ) + | |||
vector.getY() * (cosX * cosZ + sinX * sinY * sinZ) + | |||
vector.getZ() * (-sinX * cosZ + cosX * sinY * sinZ); | |||
double z = vector.getX() * (-sinY) + | |||
vector.getY() * (sinX * cosY) + | |||
vector.getZ() * (cosX * cosY); | |||
return new Vector3d(x, y, z); | |||
} | |||
public DotsEffectRunnable(Viewer viewer, Locatable locatable, Vector3d offset) { | |||
super(viewer, locatable, offset); | |||
} | |||
@Override | |||
public void run() { | |||
Vector3d position = getPosition(); | |||
ParticleEffect effect = isPerAnimationColor() ? | |||
ParticleEffect.builder(). | |||
from(getParticleEffect()). | |||
option(ParticleOptions.COLOR, CosmeticsUtils.getRandomColor()). | |||
build() : | |||
getParticleEffect(); | |||
for (int i = 0; i < getDots().length; i++) { | |||
boolean[] array = getDots()[i]; | |||
for (int j = 0; j < array.length; j++) { | |||
if (isPerParticleColor()) { | |||
effect = ParticleEffect.builder(). | |||
from(getParticleEffect()). | |||
option(ParticleOptions.COLOR, CosmeticsUtils.getRandomColor()). | |||
build(); | |||
} | |||
if (array[j]) { | |||
//TODO learn math and implement rotation on X and Z axises. | |||
//Plz help. | |||
getViewer().spawnParticles(effect, position. | |||
add(getY1Multiplier() * j * getHorizontalParticleDistance(), | |||
i * getVerticalParticleDistance(), | |||
getY2Multiplier() * j * getHorizontalParticleDistance())); | |||
} | |||
} | |||
Vector3d rotationAngles = getRotation(); | |||
Vector3d center = getPosition(); | |||
for (Map.Entry<Vector3d, ParticleEffect> entry : getDots().entrySet()) { | |||
Vector3d dot = entry.getKey(); | |||
ParticleEffect particleEffect = entry.getValue(); | |||
Vector3d point = center.add(rotate(dot, rotationAngles.getX(), rotationAngles.getY(), rotationAngles.getZ())); | |||
getViewer().spawnParticles(particleEffect, point); | |||
} | |||
} | |||
} |
@@ -6,6 +6,7 @@ import dev.gwm.spongeplugin.library.exception.SuperObjectConstructionException; | |||
import dev.gwm.spongeplugin.library.utils.GWMLibraryUtils; | |||
import ninja.leaping.configurate.ConfigurationNode; | |||
import org.spongepowered.api.effect.particle.ParticleEffect; | |||
import org.spongepowered.api.effect.particle.ParticleOptions; | |||
import java.util.Optional; | |||
@@ -15,7 +16,6 @@ public abstract class BaseCosmeticEffect extends AbstractCosmeticEffect { | |||
private final boolean perAnimationColor; | |||
private final boolean perParticleColor; | |||
public BaseCosmeticEffect(ConfigurationNode node) { | |||
super(node); | |||
try { | |||
@@ -43,6 +43,13 @@ public abstract class BaseCosmeticEffect extends AbstractCosmeticEffect { | |||
this.perParticleColor = perParticleColor; | |||
} | |||
public ParticleEffect getColoredParticleEffect() { | |||
return ParticleEffect.builder(). | |||
from(getParticleEffect()). | |||
option(ParticleOptions.COLOR, CosmeticsUtils.getRandomColor()). | |||
build(); | |||
} | |||
public ParticleEffect getParticleEffect() { | |||
return particleEffect; | |||
} | |||