mirror of
https://github.com/DieReicheErethons/Brewery.git
synced 2025-01-25 21:41:19 +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.recipe.RecipeItem;
|
||||||
import com.dre.brewery.utility.BUtil;
|
import com.dre.brewery.utility.BUtil;
|
||||||
import com.dre.brewery.utility.LegacyUtil;
|
import com.dre.brewery.utility.LegacyUtil;
|
||||||
|
import com.dre.brewery.utility.Tuple;
|
||||||
|
import org.bukkit.Color;
|
||||||
import org.bukkit.Effect;
|
import org.bukkit.Effect;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -19,6 +21,7 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -32,17 +35,17 @@ public class BCauldron {
|
|||||||
private static Set<UUID> plInteracted = new HashSet<>(); // Interact Event helper
|
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 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 BIngredients ingredients = new BIngredients();
|
||||||
private final Block block;
|
private final Block block;
|
||||||
private int state = 0;
|
private int state = 0;
|
||||||
private boolean changed = false;
|
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;
|
private Location particleLocation;
|
||||||
|
|
||||||
public BCauldron(Block block) {
|
public BCauldron(Block block) {
|
||||||
this.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
|
// loading from file
|
||||||
@ -50,7 +53,7 @@ public class BCauldron {
|
|||||||
this.block = block;
|
this.block = block;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.ingredients = ingredients;
|
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();
|
ingredients = ingredients.copy();
|
||||||
changed = false;
|
changed = false;
|
||||||
}
|
}
|
||||||
|
particleColor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add an ingredient to the cauldron
|
// add an ingredient to the cauldron
|
||||||
@ -94,6 +98,8 @@ public class BCauldron {
|
|||||||
changed = false;
|
changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
particleRecipe = null;
|
||||||
|
particleColor = null;
|
||||||
ingredients.add(ingredient, rItem);
|
ingredients.add(ingredient, rItem);
|
||||||
block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0);
|
block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0);
|
||||||
if (state > 0) {
|
if (state > 0) {
|
||||||
@ -233,18 +239,28 @@ public class BCauldron {
|
|||||||
|
|
||||||
public void cookEffect() {
|
public void cookEffect() {
|
||||||
if (BUtil.isChunkLoaded(block) && LegacyUtil.isCauldronHeatsource(block.getRelative(BlockFace.DOWN))) {
|
if (BUtil.isChunkLoaded(block) && LegacyUtil.isCauldronHeatsource(block.getRelative(BlockFace.DOWN))) {
|
||||||
if (particleRandom.nextFloat() > 0.75) {
|
if (particleRandom.nextFloat() > 0.85) {
|
||||||
// Pixely cloud at 0.4 random in x and z
|
// Dark pixely smoke cloud at 0.4 random in x and z
|
||||||
// 0 count enables direction, send to y = 1 with speed 0.07
|
// 0 count enables direction, send to y = 1 with speed 0.09
|
||||||
block.getWorld().spawnParticle(Particle.CLOUD, getRandParticleLoc(), 0, 0, 1, 0, 0.07);
|
block.getWorld().spawnParticle(Particle.SMOKE_LARGE, getRandParticleLoc(), 0, 0, 1, 0, 0.09);
|
||||||
}
|
}
|
||||||
if (particleRandom.nextFloat() > 0.2) {
|
if (particleRandom.nextFloat() > 0.2) {
|
||||||
// A Water Splash with 0.2 offset in x and z
|
// A Water Splash with 0.2 offset in x and z
|
||||||
block.getWorld().spawnParticle(Particle.WATER_SPLASH, particleLocation, 1, 0.2, 0, 0.2);
|
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
|
// 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
|
// 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);
|
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;
|
if (!BConfig.enableCauldronParticles) return;
|
||||||
int size = bcauldrons.size();
|
int size = bcauldrons.size();
|
||||||
if (size <= 0) {
|
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
|
* reset to normal cauldron
|
||||||
*/
|
*/
|
||||||
|
@ -198,6 +198,9 @@ public class P extends JavaPlugin {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reload Cauldron Particle Recipes
|
||||||
|
BCauldron.reload();
|
||||||
|
|
||||||
// Reload Recipes
|
// Reload Recipes
|
||||||
boolean successful = true;
|
boolean successful = true;
|
||||||
for (Brew brew : Brew.legacyPotions.values()) {
|
for (Brew brew : Brew.legacyPotions.values()) {
|
||||||
@ -485,7 +488,7 @@ public class P extends JavaPlugin {
|
|||||||
public class CauldronParticles implements Runnable {
|
public class CauldronParticles implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,8 +24,8 @@ public class BCauldronRecipe {
|
|||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private List<RecipeItem> ingredients;
|
private List<RecipeItem> ingredients;
|
||||||
//private List<String> particles
|
|
||||||
private PotionColor color;
|
private PotionColor color;
|
||||||
|
private List<Tuple<Integer, Color>> particleColor = new ArrayList<>();
|
||||||
private List<String> lore;
|
private List<String> lore;
|
||||||
private int cmData; // Custom Model Data
|
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
|
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;
|
//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");
|
List<Tuple<Integer,String>> lore = BRecipe.loadLore(cfg, id + ".lore");
|
||||||
if (lore != null && !lore.isEmpty()) {
|
if (lore != null && !lore.isEmpty()) {
|
||||||
@ -107,6 +130,11 @@ public class BCauldronRecipe {
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<Tuple<Integer, Color>> getParticleColor() {
|
||||||
|
return particleColor;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public List<String> getLore() {
|
public List<String> getLore() {
|
||||||
return lore;
|
return lore;
|
||||||
@ -337,6 +365,11 @@ public class BCauldronRecipe {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder addParticleColor(int atMinute, Color color) {
|
||||||
|
recipe.particleColor.add(new Tuple<>(atMinute, color));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder addLore(String line) {
|
public Builder addLore(String line) {
|
||||||
if (recipe.lore == null) {
|
if (recipe.lore == null) {
|
||||||
recipe.lore = new ArrayList<>();
|
recipe.lore = new ArrayList<>();
|
||||||
@ -358,6 +391,10 @@ public class BCauldronRecipe {
|
|||||||
if (recipe.ingredients == null || recipe.ingredients.isEmpty()) {
|
if (recipe.ingredients == null || recipe.ingredients.isEmpty()) {
|
||||||
throw new IllegalArgumentException("CauldronRecipe has no ingredients");
|
throw new IllegalArgumentException("CauldronRecipe has no ingredients");
|
||||||
}
|
}
|
||||||
|
if (!recipe.particleColor.isEmpty()) {
|
||||||
|
// Sort particleColor by minute
|
||||||
|
recipe.particleColor.sort(Comparator.comparing(Tuple::first));
|
||||||
|
}
|
||||||
return recipe;
|
return recipe;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import com.dre.brewery.P;
|
|||||||
import com.dre.brewery.api.events.barrel.BarrelDestroyEvent;
|
import com.dre.brewery.api.events.barrel.BarrelDestroyEvent;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Color;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
@ -48,6 +49,35 @@ public class BUtil {
|
|||||||
return msg;
|
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
|
* Returns either uuid or Name of player, depending on bukkit version
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user