diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties b/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties index e691bbf9..02ac4c6f 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem.properties @@ -138,6 +138,10 @@ PARTICLE_PARAM_SPREAD_Z = §fSpread Z PARTICLE_PARAM_SPEED = §fSpeed PARTICLE_PARAM_COLORS = §fColours PARTICLE_PARAM_BLOCK = §fBlock +PARTICLE_PARAM_TRAIL_DURATION = §fTrail duration (ticks) +PARTICLE_PARAM_TRAIL_TARGET_X = §fTrail target X +PARTICLE_PARAM_TRAIL_TARGET_Y = §fTrail target Y +PARTICLE_PARAM_TRAIL_TARGET_Z = §fTrail target Z PARTICLE_PARAM_OFFSET_X = §fOffset X PARTICLE_PARAM_OFFSET_Y = §fOffset Y PARTICLE_PARAM_OFFSET_Z = §fOffset Z @@ -193,6 +197,7 @@ PARTICLE_TYPE_BLOCK_MARKER = §fBlock marker PARTICLE_TYPE_DUST_PILLAR = §fDust pillar PARTICLE_TYPE_FALLING_DUST = §fFalling dust PARTICLE_TYPE_ITEM = §fItem breaking +PARTICLE_TYPE_TRAIL = §fTrail PARTICLE_TYPE_FLAME = §fFlame PARTICLE_TYPE_SMALL_FLAME = §fSmall flame PARTICLE_TYPE_SOUL_FIRE_FLAME = §fSoul fire flame diff --git a/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties b/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties index 146f66c1..4e6dd860 100644 --- a/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties +++ b/LobbySystem/src/de/steamwar/lobby/LobbySystem_de.properties @@ -138,6 +138,10 @@ PARTICLE_PARAM_SPREAD_Z = §fStreuung Z PARTICLE_PARAM_SPEED = §fGeschwindigkeit PARTICLE_PARAM_COLORS = §fFarben PARTICLE_PARAM_BLOCK = §fBlock +PARTICLE_PARAM_TRAIL_DURATION = §fSpurdauer (Ticks) +PARTICLE_PARAM_TRAIL_TARGET_X = §fSpurziel X +PARTICLE_PARAM_TRAIL_TARGET_Y = §fSpurziel Y +PARTICLE_PARAM_TRAIL_TARGET_Z = §fSpurziel Z PARTICLE_PARAM_OFFSET_X = §fVersatz X PARTICLE_PARAM_OFFSET_Y = §fVersatz Y PARTICLE_PARAM_OFFSET_Z = §fVersatz Z @@ -193,6 +197,7 @@ PARTICLE_TYPE_BLOCK_MARKER = §fBlockmarkierung PARTICLE_TYPE_DUST_PILLAR = §fStaubsäule PARTICLE_TYPE_FALLING_DUST = §fFallender Staub PARTICLE_TYPE_ITEM = §fGegenstandssplitter +PARTICLE_TYPE_TRAIL = §fSpur PARTICLE_TYPE_FLAME = §fFlamme PARTICLE_TYPE_SMALL_FLAME = §fKleine Flamme PARTICLE_TYPE_SOUL_FIRE_FLAME = §fSeelenfeuerflamme diff --git a/LobbySystem/src/de/steamwar/lobby/particle/TODOs.md b/LobbySystem/src/de/steamwar/lobby/particle/TODOs.md deleted file mode 100644 index 823a020f..00000000 --- a/LobbySystem/src/de/steamwar/lobby/particle/TODOs.md +++ /dev/null @@ -1 +0,0 @@ -Relative zur rotation den spielers und co \ No newline at end of file diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java b/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java index 69e73263..10da5052 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java @@ -189,6 +189,11 @@ public class EntryParameters { public final DoubleParameter OFFSET_Y = new DoubleParameter("offsetY", "PARTICLE_PARAM_OFFSET_Y", 0, -3, 3, 0.1); public final DoubleParameter OFFSET_Z = new DoubleParameter("offsetZ", "PARTICLE_PARAM_OFFSET_Z", 0, -3, 3, 0.1); public final IntParameter INTERVAL = new IntParameter("interval", "PARTICLE_PARAM_INTERVAL", 1, 1, 100); + public final IntParameter TRAIL_DURATION = new IntParameter("trailDuration", "PARTICLE_PARAM_TRAIL_DURATION", 20, 1, 200); + // Where a trail particle flies to, relative to where it spawns + public final DoubleParameter TRAIL_TARGET_X = new DoubleParameter("trailTargetX", "PARTICLE_PARAM_TRAIL_TARGET_X", 0, -5, 5, 0.1); + public final DoubleParameter TRAIL_TARGET_Y = new DoubleParameter("trailTargetY", "PARTICLE_PARAM_TRAIL_TARGET_Y", 1, -5, 5, 0.1); + public final DoubleParameter TRAIL_TARGET_Z = new DoubleParameter("trailTargetZ", "PARTICLE_PARAM_TRAIL_TARGET_Z", 0, -5, 5, 0.1); public final ChoiceParameter PLACEMENT = ChoiceParameter.ofEnum("placement", "PARTICLE_PARAM_PLACEMENT", Placement.WORLD); public final ChoiceParameter TICK_MODE = ChoiceParameter.ofEnum("tickMode", "PARTICLE_PARAM_TICK_MODE", TickMode.MOVE); public final ChoiceParameter MOVEMENT = ChoiceParameter.ofEnum("movement", "PARTICLE_PARAM_MOVEMENT", Movement.ANY); @@ -199,6 +204,7 @@ public class EntryParameters { public final List> ALL = List.of( PARTICLE, COUNT, SPREAD_X, SPREAD_Y, SPREAD_Z, SPEED, COLORS, BLOCK, + TRAIL_DURATION, TRAIL_TARGET_X, TRAIL_TARGET_Y, TRAIL_TARGET_Z, OFFSET_X, OFFSET_Y, OFFSET_Z, PLACEMENT, INTERVAL, TICK_MODE, MOVEMENT, GLIDING, GROUND, SNEAK, VISIBILITY ); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java index 16d70fc8..bdd9b3f5 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java @@ -25,7 +25,7 @@ import org.bukkit.Material; import org.bukkit.Particle; // Left out: ELDER_GUARDIAN, FLASH and the explosion/gust emitters cover other players' screens, -// BUBBLE, BUBBLE_COLUMN_UP and CURRENT_DOWN only show under water, VIBRATION and TRAIL need a target +// BUBBLE, BUBBLE_COLUMN_UP and CURRENT_DOWN only show under water, VIBRATION needs a block or entity to fly to @AllArgsConstructor @Getter public enum ParticleType { @@ -40,6 +40,7 @@ public enum ParticleType { DUST_PILLAR(Material.MUD, Particle.DUST_PILLAR, Data.BLOCK, true), FALLING_DUST(Material.SAND, Particle.FALLING_DUST, Data.BLOCK, true), ITEM(Material.ITEM_FRAME, Particle.ITEM, Data.ITEM, true), + TRAIL(Material.LEAD, Particle.TRAIL, Data.TRAIL, true), FLAME(Material.FLINT_AND_STEEL, Particle.FLAME, Data.NONE, true), SMALL_FLAME(Material.TORCH, Particle.SMALL_FLAME, Data.NONE, true), @@ -153,6 +154,8 @@ public enum ParticleType { BLOCK, // An item of the entry's block ITEM, + // Flies to the entry's trail target in its colour, taking the trail duration + TRAIL, ZERO_INT, ZERO_FLOAT, } @@ -171,7 +174,11 @@ public enum ParticleType { } public boolean usesColors() { - return data == Data.DUST || data == Data.COLOR || data == Data.COLOR_TRANSITION; + return data == Data.DUST || data == Data.COLOR || data == Data.COLOR_TRANSITION || data == Data.TRAIL; + } + + public boolean isTrail() { + return data == Data.TRAIL; } public boolean usesBlock() { diff --git a/LobbySystem/src/de/steamwar/lobby/particle/elements/DataParticle.java b/LobbySystem/src/de/steamwar/lobby/particle/elements/DataParticle.java index 0f5d87c6..5f8d3fce 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/elements/DataParticle.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/elements/DataParticle.java @@ -26,9 +26,9 @@ import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Particle; -import java.util.function.Function; +import java.util.function.BiFunction; -// A particle that needs extra data, computed per tick so colours can follow a gradient +// A particle that needs extra data, computed per tick from the tick and spawn location so colours can follow a gradient public class DataParticle implements ParticleElement { private final Particle particle; @@ -37,9 +37,9 @@ public class DataParticle implements ParticleElement { private final float vz; private final double speed; private final int count; - private final Function data; + private final BiFunction data; - public DataParticle(Particle particle, float vx, float vy, float vz, double speed, int count, Function data) { + public DataParticle(Particle particle, float vx, float vy, float vz, double speed, int count, BiFunction data) { this.particle = particle; this.vx = vx; this.vy = vy; @@ -61,7 +61,7 @@ public class DataParticle implements ParticleElement { @Override public void tick(ParticleTickData particleTickData) { Location location = particleTickData.getLocation().add(0.0, 0.2, 0.0); - Object value = data.apply(particleTickData); + Object value = data.apply(particleTickData, location); display(particleTickData, player -> player.spawnParticle(particle, location, count, vx, vy, vz, speed, value)); } } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java b/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java index 0eb5bff9..63e1361d 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java @@ -70,6 +70,10 @@ class EntryEditor { Map.entry(INTERVAL, Material.CLOCK), Map.entry(TICK_MODE, Material.REPEATER), Map.entry(PLACEMENT, Material.PLAYER_HEAD), + Map.entry(TRAIL_DURATION, Material.CLOCK), + Map.entry(TRAIL_TARGET_X, Material.LEAD), + Map.entry(TRAIL_TARGET_Y, Material.LEAD), + Map.entry(TRAIL_TARGET_Z, Material.LEAD), Map.entry(MOVEMENT, Material.LEATHER_BOOTS), Map.entry(GLIDING, Material.ELYTRA), Map.entry(GROUND, Material.GRASS_BLOCK), @@ -119,6 +123,12 @@ class EntryEditor { } else if (type.usesBlock()) { inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 2, parameterItem(context, BLOCK)); } + if (type.isTrail()) { + List> trail = List.of(TRAIL_DURATION, TRAIL_TARGET_X, TRAIL_TARGET_Y, TRAIL_TARGET_Z); + for (int i = 0; i < trail.size(); i++) { + inventory.setItem(ROW_DESIGN * 9 + FIRST_SETTING + 3 + i, parameterItem(context, trail.get(i))); + } + } row(inventory, context, ROW_PARTICLE, List.of(COUNT, SPEED, SPREAD_X, SPREAD_Y, SPREAD_Z)); } else { inventory.setItem(ROW_PARTICLE * 9 + FIRST_SETTING, new SWItem(Material.STRUCTURE_VOID, msg("PARTICLE_FIXED_LOOK", player), clickType -> { diff --git a/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java b/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java index f41cebd1..fd240eae 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java @@ -27,15 +27,17 @@ import de.steamwar.lobby.particle.ParticleTickData; import de.steamwar.lobby.particle.design.*; import de.steamwar.lobby.particle.elements.*; import lombok.Getter; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; import org.bukkit.block.data.BlockData; import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; import java.awt.Color; import java.util.ArrayList; import java.util.List; -import java.util.function.Function; +import java.util.function.BiFunction; import static de.steamwar.lobby.particle.design.EntryParameters.*; @@ -109,24 +111,32 @@ public class ParticleEntry { List colors = values.get(COLORS); Gradient gradient = colors.isEmpty() ? null : new Gradient(colors.toArray(new Color[0])); Material block = values.get(BLOCK); - Function data = switch (type.getData()) { + BiFunction data = switch (type.getData()) { // Dust keeps its own element below, so presets look exactly as before case NONE, DUST -> null; - case COLOR -> tick -> DataParticle.color(gradient, tick); - case COLOR_TRANSITION -> tick -> new Particle.DustTransition( + case COLOR -> (tick, location) -> DataParticle.color(gradient, tick); + case COLOR_TRANSITION -> (tick, location) -> new Particle.DustTransition( colors.isEmpty() ? DataParticle.color(null, tick) : bukkitColor(colors.get(0)), colors.size() < 2 ? DataParticle.color(null, tick) : bukkitColor(colors.get(1)), 1); case BLOCK -> { BlockData blockData = block.createBlockData(); - yield tick -> blockData; + yield (tick, location) -> blockData; } case ITEM -> { ItemStack item = new ItemStack(block); - yield tick -> item; + yield (tick, location) -> item; } - case ZERO_INT -> tick -> 0; - case ZERO_FLOAT -> tick -> 0f; + case TRAIL -> { + int duration = values.get(TRAIL_DURATION); + Vector target = new Vector(values.get(TRAIL_TARGET_X), values.get(TRAIL_TARGET_Y), values.get(TRAIL_TARGET_Z)); + // The target follows the body like offsets do when the entry is placed relative to it + yield (tick, location) -> new Particle.Trail( + location.clone().add(tick.getFrame() == null ? target : tick.getFrame().local(target.getX(), target.getY(), target.getZ())), + DataParticle.color(gradient, tick), duration); + } + case ZERO_INT -> (tick, location) -> 0; + case ZERO_FLOAT -> (tick, location) -> 0f; }; if (type.isDust()) {