mirror of
https://github.com/DieReicheErethons/Brewery.git
synced 2024-11-14 10:15:38 +01:00
Color fading for Cauldron Particles
This commit is contained in:
parent
29830e0405
commit
db1a425215
@ -6,6 +6,8 @@ import com.dre.brewery.recipe.BCauldronRecipe;
|
||||
import com.dre.brewery.recipe.RecipeItem;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import com.dre.brewery.utility.LegacyUtil;
|
||||
import com.dre.brewery.utility.Tuple;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -19,6 +21,7 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
@ -32,17 +35,17 @@ public class BCauldron {
|
||||
private static Set<UUID> plInteracted = new HashSet<>(); // Interact Event helper
|
||||
public static Map<Block, BCauldron> bcauldrons = new HashMap<>(); // All active cauldrons. Mapped to their block for fast retrieve
|
||||
|
||||
public static Particle particle = Particle.CLOUD;
|
||||
|
||||
private BIngredients ingredients = new BIngredients();
|
||||
private final Block block;
|
||||
private int state = 0;
|
||||
private boolean changed = false;
|
||||
private Optional<BCauldronRecipe> particleRecipe; // null if we haven't checked, empty if there is none
|
||||
private Color particleColor;
|
||||
private Location particleLocation;
|
||||
|
||||
public BCauldron(Block block) {
|
||||
this.block = block;
|
||||
particleLocation = block.getLocation().add(0.5, 0.8, 0.5);
|
||||
particleLocation = block.getLocation().add(0.5, 0.9, 0.5);
|
||||
}
|
||||
|
||||
// loading from file
|
||||
@ -50,7 +53,7 @@ public class BCauldron {
|
||||
this.block = block;
|
||||
this.state = state;
|
||||
this.ingredients = ingredients;
|
||||
particleLocation = block.getLocation().add(0.5, 0.8, 0.5);
|
||||
particleLocation = block.getLocation().add(0.5, 0.9, 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,6 +87,7 @@ public class BCauldron {
|
||||
ingredients = ingredients.copy();
|
||||
changed = false;
|
||||
}
|
||||
particleColor = null;
|
||||
}
|
||||
|
||||
// add an ingredient to the cauldron
|
||||
@ -94,6 +98,8 @@ public class BCauldron {
|
||||
changed = false;
|
||||
}
|
||||
|
||||
particleRecipe = null;
|
||||
particleColor = null;
|
||||
ingredients.add(ingredient, rItem);
|
||||
block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0);
|
||||
if (state > 0) {
|
||||
@ -233,18 +239,28 @@ public class BCauldron {
|
||||
|
||||
public void cookEffect() {
|
||||
if (BUtil.isChunkLoaded(block) && LegacyUtil.isCauldronHeatsource(block.getRelative(BlockFace.DOWN))) {
|
||||
if (particleRandom.nextFloat() > 0.75) {
|
||||
// Pixely cloud at 0.4 random in x and z
|
||||
// 0 count enables direction, send to y = 1 with speed 0.07
|
||||
block.getWorld().spawnParticle(Particle.CLOUD, getRandParticleLoc(), 0, 0, 1, 0, 0.07);
|
||||
if (particleRandom.nextFloat() > 0.85) {
|
||||
// Dark pixely smoke cloud at 0.4 random in x and z
|
||||
// 0 count enables direction, send to y = 1 with speed 0.09
|
||||
block.getWorld().spawnParticle(Particle.SMOKE_LARGE, getRandParticleLoc(), 0, 0, 1, 0, 0.09);
|
||||
}
|
||||
if (particleRandom.nextFloat() > 0.2) {
|
||||
// A Water Splash with 0.2 offset in x and z
|
||||
block.getWorld().spawnParticle(Particle.WATER_SPLASH, particleLocation, 1, 0.2, 0, 0.2);
|
||||
}
|
||||
Color color = getParticleColor();
|
||||
// Colorable spirally spell, 0 count enables color instead of the offset variables
|
||||
// Configurable RGB color. 1025 seems to be the best for color brightness and upwards motion
|
||||
block.getWorld().spawnParticle(Particle.SPELL_MOB, getRandParticleLoc(), 0, 180.0/255.0, 40.0/255.0, 1.0/255.0, 1025.0);
|
||||
block.getWorld().spawnParticle(Particle.SPELL_MOB, getRandParticleLoc(), 0,
|
||||
((double) color.getRed()) / 255.0,
|
||||
((double) color.getGreen()) / 255.0,
|
||||
((double) color.getBlue()) / 255.0,
|
||||
1025.0);
|
||||
|
||||
if (particleRandom.nextFloat() > 0.4) {
|
||||
// Two hovering pixely dust clouds, a bit offset with DustOptions to give some color and size
|
||||
block.getWorld().spawnParticle(Particle.REDSTONE, particleLocation, 2, 0.15, 0.2, 0.15, new Particle.DustOptions(color, 1.5f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,7 +271,82 @@ public class BCauldron {
|
||||
particleLocation.getZ() + (particleRandom.nextDouble() * 0.8) - 0.4);
|
||||
}
|
||||
|
||||
public static void cookEffects() {
|
||||
/**
|
||||
* Get or calculate the particle color from the current best Cauldron Recipe
|
||||
* Also calculates the best Cauldron Recipe if not yet done
|
||||
*
|
||||
* @return the Particle Color, after potentially calculating it
|
||||
*/
|
||||
@NotNull
|
||||
public Color getParticleColor() {
|
||||
if (state < 1) {
|
||||
return Color.fromRGB(153, 221, 255); // Bright Blue
|
||||
}
|
||||
if (particleColor != null) {
|
||||
return particleColor;
|
||||
}
|
||||
if (particleRecipe == null) {
|
||||
// Check for Cauldron Recipe
|
||||
particleRecipe = Optional.ofNullable(ingredients.getCauldronRecipe());
|
||||
}
|
||||
|
||||
List<Tuple<Integer, Color>> colorList = null;
|
||||
if (particleRecipe.isPresent()) {
|
||||
colorList = particleRecipe.get().getParticleColor();
|
||||
}
|
||||
|
||||
if (colorList == null || colorList.isEmpty()) {
|
||||
// No color List configured, or no recipe found
|
||||
colorList = new ArrayList<>(1);
|
||||
colorList.add(new Tuple<>(10, Color.fromRGB(77, 166, 255))); // Dark Aqua kind of Blue
|
||||
}
|
||||
int index = 0;
|
||||
while (index < colorList.size() - 1 && colorList.get(index).a() < state) {
|
||||
// Find the first index where the colorList Minute is higher than the state
|
||||
index++;
|
||||
}
|
||||
|
||||
int minute = colorList.get(index).a();
|
||||
if (minute > state) {
|
||||
// going towards the minute
|
||||
int prevPos;
|
||||
Color prevColor;
|
||||
if (index > 0) {
|
||||
// has previous colours
|
||||
prevPos = colorList.get(index - 1).a();
|
||||
prevColor = colorList.get(index - 1).b();
|
||||
} else {
|
||||
prevPos = 0;
|
||||
prevColor = Color.fromRGB(153, 221, 255); // Bright Blue
|
||||
}
|
||||
|
||||
particleColor = BUtil.weightedMixColor(prevColor, prevPos, state, colorList.get(index).b(), minute);
|
||||
} else if (minute == state) {
|
||||
// reached the minute
|
||||
particleColor = colorList.get(index).b();
|
||||
} else {
|
||||
// passed the last minute configured
|
||||
if (index > 0) {
|
||||
// We have more than one color, just use the last one
|
||||
particleColor = colorList.get(index).b();
|
||||
} else {
|
||||
// Only have one color, go towards a Gray
|
||||
Color nextColor = Color.fromRGB(138, 153, 168); // Dark Teal, Gray
|
||||
int nextPos = (int) (minute * 2.6f);
|
||||
|
||||
if (nextPos <= state) {
|
||||
// We are past the next color (Gray) as well, keep using it
|
||||
particleColor = nextColor;
|
||||
} else {
|
||||
particleColor = BUtil.weightedMixColor(colorList.get(index).b(), minute, state, nextColor, nextPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
//P.p.log("RGB: " + particleColor.getRed() + "|" + particleColor.getGreen() + "|" + particleColor.getBlue());
|
||||
return particleColor;
|
||||
}
|
||||
|
||||
public static void processNextCookEffects() {
|
||||
if (!BConfig.enableCauldronParticles) return;
|
||||
int size = bcauldrons.size();
|
||||
if (size <= 0) {
|
||||
@ -422,6 +513,21 @@ public class BCauldron {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate the Cauldron Particle Recipe
|
||||
*/
|
||||
public static void reload() {
|
||||
for (BCauldron cauldron : BCauldron.bcauldrons.values()) {
|
||||
cauldron.particleRecipe = null;
|
||||
cauldron.particleColor = null;
|
||||
if (BConfig.enableCauldronParticles) {
|
||||
if (BUtil.isChunkLoaded(cauldron.block) && LegacyUtil.isCauldronHeatsource(cauldron.block.getRelative(BlockFace.DOWN))) {
|
||||
cauldron.getParticleColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* reset to normal cauldron
|
||||
*/
|
||||
|
@ -198,6 +198,9 @@ public class P extends JavaPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reload Cauldron Particle Recipes
|
||||
BCauldron.reload();
|
||||
|
||||
// Reload Recipes
|
||||
boolean successful = true;
|
||||
for (Brew brew : Brew.legacyPotions.values()) {
|
||||
@ -485,7 +488,7 @@ public class P extends JavaPlugin {
|
||||
public class CauldronParticles implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
BCauldron.cookEffects();
|
||||
BCauldron.processNextCookEffects();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -28,8 +24,8 @@ public class BCauldronRecipe {
|
||||
|
||||
private String name;
|
||||
private List<RecipeItem> ingredients;
|
||||
//private List<String> particles
|
||||
private PotionColor color;
|
||||
private List<Tuple<Integer, Color>> particleColor = new ArrayList<>();
|
||||
private List<String> lore;
|
||||
private int cmData; // Custom Model Data
|
||||
private boolean saveInData; // If this recipe should be saved in data and loaded again when the server restarts. Applicable to non-config recipes
|
||||
@ -78,6 +74,33 @@ public class BCauldronRecipe {
|
||||
//return null;
|
||||
}
|
||||
|
||||
for (String entry : cfg.getStringList(id + ".cookParticles")) {
|
||||
String[] split = entry.split("/");
|
||||
int minute;
|
||||
if (split.length == 1) {
|
||||
minute = 10;
|
||||
} else if (split.length == 2) {
|
||||
minute = P.p.parseInt(split[1]);
|
||||
} else {
|
||||
P.p.errorLog("cookParticle: '" + entry + "' in: " + recipe.name);
|
||||
return null;
|
||||
}
|
||||
if (minute < 1) {
|
||||
P.p.errorLog("cookParticle: '" + entry + "' in: " + recipe.name);
|
||||
return null;
|
||||
}
|
||||
PotionColor partCol = PotionColor.fromString(split[0]);
|
||||
if (partCol == PotionColor.WATER && !split[0].equals("WATER")) {
|
||||
P.p.errorLog("Color of cookParticle: '" + entry + "' in: " + recipe.name);
|
||||
return null;
|
||||
}
|
||||
recipe.particleColor.add(new Tuple<>(minute, partCol.getColor()));
|
||||
}
|
||||
if (!recipe.particleColor.isEmpty()) {
|
||||
// Sort by minute
|
||||
recipe.particleColor.sort(Comparator.comparing(Tuple::first));
|
||||
}
|
||||
|
||||
|
||||
List<Tuple<Integer,String>> lore = BRecipe.loadLore(cfg, id + ".lore");
|
||||
if (lore != null && !lore.isEmpty()) {
|
||||
@ -107,6 +130,11 @@ public class BCauldronRecipe {
|
||||
return color;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Tuple<Integer, Color>> getParticleColor() {
|
||||
return particleColor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
@ -337,6 +365,11 @@ public class BCauldronRecipe {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addParticleColor(int atMinute, Color color) {
|
||||
recipe.particleColor.add(new Tuple<>(atMinute, color));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addLore(String line) {
|
||||
if (recipe.lore == null) {
|
||||
recipe.lore = new ArrayList<>();
|
||||
@ -358,6 +391,10 @@ public class BCauldronRecipe {
|
||||
if (recipe.ingredients == null || recipe.ingredients.isEmpty()) {
|
||||
throw new IllegalArgumentException("CauldronRecipe has no ingredients");
|
||||
}
|
||||
if (!recipe.particleColor.isEmpty()) {
|
||||
// Sort particleColor by minute
|
||||
recipe.particleColor.sort(Comparator.comparing(Tuple::first));
|
||||
}
|
||||
return recipe;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.dre.brewery.P;
|
||||
import com.dre.brewery.api.events.barrel.BarrelDestroyEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
@ -48,6 +49,35 @@ public class BUtil {
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a weighted mix between the two given colours
|
||||
* <p>where the weight is calculated from the distance of the currentPos to the prev and next
|
||||
*
|
||||
* @param prevColor Previous Color
|
||||
* @param prevPos Position of the Previous Color
|
||||
* @param currentPos Current Position
|
||||
* @param nextColor Next Color
|
||||
* @param nextPos Position of the Next Color
|
||||
* @return
|
||||
*/
|
||||
public static Color weightedMixColor(Color prevColor, int prevPos, int currentPos, Color nextColor, int nextPos) {
|
||||
float diffPrev = currentPos - prevPos;
|
||||
float diffNext = nextPos - currentPos;
|
||||
float total = diffNext + diffPrev;
|
||||
float percentNext = diffPrev / total;
|
||||
float percentPrev = diffNext / total;
|
||||
|
||||
/*5 #8# 15
|
||||
8-5 = 3 -> 3/10
|
||||
15-8 = 7 -> 7/10*/
|
||||
|
||||
return Color.fromRGB(
|
||||
Math.min(255, (int) ((nextColor.getRed() * percentNext) + (prevColor.getRed() * percentPrev))),
|
||||
Math.min(255, (int) ((nextColor.getGreen() * percentNext) + (prevColor.getGreen() * percentPrev))),
|
||||
Math.min(255, (int) ((nextColor.getBlue() * percentNext) + (prevColor.getBlue() * percentPrev)))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns either uuid or Name of player, depending on bukkit version
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user