From 8fd6fdf81ed0fae6de5f519e3e5316aa4e3a91a0 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 26 Oct 2026 14:37:40 +0100 Subject: [PATCH] Unlock tournament wing images and cosy smoke for building The MiniWarGear league, Underwater MWG, WarGear season 2022 and WarGear clash wing images become Wings shapes, locked behind the placement that earns their reward. Cosy campfire smoke becomes a buildable particle for Hells Bells participants. Choice options can now carry a requirement: locked options show it in the picker, are skipped when cycling and hide entries that use them. --- .../particle/design/ChoiceParameter.java | 24 +++++++++++++++---- .../lobby/particle/design/Designs.java | 9 +++---- .../particle/design/EntryParameters.java | 2 +- .../lobby/particle/design/ParticleType.java | 6 +++-- .../lobby/particle/gui/EntryEditor.java | 10 ++++---- .../lobby/particle/slot/ParticleEntry.java | 10 ++++++-- 6 files changed, 44 insertions(+), 17 deletions(-) diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/ChoiceParameter.java b/LobbySystem/src/de/steamwar/lobby/particle/design/ChoiceParameter.java index 9df4eed0..76876caf 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/ChoiceParameter.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/ChoiceParameter.java @@ -21,17 +21,25 @@ package de.steamwar.lobby.particle.design; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; +import de.steamwar.lobby.particle.ParticleRequirement; import lombok.Getter; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; import java.util.function.Predicate; +import java.util.function.Supplier; @Getter public class ChoiceParameter extends Parameter { - // Internal choices are usable by presets but never offered in the builder or accepted from storage - public record Choice(String id, E value, boolean internal) { + // Internal choices are usable by presets but never offered in the builder or accepted from storage. Locked choices + // are offered with their requirement; the requirement is looked up lazily as it may live in a reward design. + public record Choice(String id, E value, boolean internal, Supplier requirement) { + + public Choice(String id, E value, boolean internal) { + this(id, value, internal, () -> ParticleRequirement.NO_REQUIRMENT); + } } private final List> choices; @@ -41,14 +49,18 @@ public class ChoiceParameter extends Parameter { this.choices = choices; } - public static > ChoiceParameter ofEnum(String key, String nameKey, E defaultValue, Predicate internal) { + public static > ChoiceParameter ofEnum(String key, String nameKey, E defaultValue, Predicate internal, Function requirement) { List> choices = new ArrayList<>(); for (E value : defaultValue.getDeclaringClass().getEnumConstants()) { - choices.add(new Choice<>(value.name(), value, internal.test(value))); + choices.add(new Choice<>(value.name(), value, internal.test(value), () -> requirement.apply(value))); } return new ChoiceParameter<>(key, nameKey, defaultValue, choices); } + public static > ChoiceParameter ofEnum(String key, String nameKey, E defaultValue, Predicate internal) { + return ofEnum(key, nameKey, defaultValue, internal, value -> ParticleRequirement.NO_REQUIRMENT); + } + public static > ChoiceParameter ofEnum(String key, String nameKey, E defaultValue) { return ofEnum(key, nameKey, defaultValue, value -> false); } @@ -57,6 +69,10 @@ public class ChoiceParameter extends Parameter { return choices.stream().filter(choice -> !choice.internal()).map(Choice::value).toList(); } + public ParticleRequirement requirement(E value) { + return choiceOf(value).requirement().get(); + } + @Override public JsonElement toJson(E value) { return new JsonPrimitive(choiceOf(value).id()); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java b/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java index 892d6b4f..d2a05cf9 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/Designs.java @@ -74,10 +74,11 @@ public class Designs { new ChoiceParameter.Choice<>("bat", WingShape.drawn(DrawnWings.BAT), false), new ChoiceParameter.Choice<>("butterfly", WingShape.drawn(DrawnWings.BUTTERFLY), false), new ChoiceParameter.Choice<>("fairy", WingShape.drawn(DrawnWings.FAIRY), false), - new ChoiceParameter.Choice<>("sw", WingShape.image(WingDesign.SW), true), - new ChoiceParameter.Choice<>("wgs", WingShape.image(WingDesign.WGS), true), - new ChoiceParameter.Choice<>("sword_crossed", WingShape.image(WingDesign.SWORD_CROSSED), true), - new ChoiceParameter.Choice<>("mwgl", WingShape.image(WingDesign.MWGL), true), + // Tournament wing images, unlocked by the placement that earns their reward + new ChoiceParameter.Choice<>("mwgl", WingShape.image(WingDesign.MWGL), false, () -> RewardDesigns.EVENT_PLACEMENT_MINI_WARGEAR_LIGA.getRequirement()), + new ChoiceParameter.Choice<>("sw", WingShape.image(WingDesign.SW), false, () -> RewardDesigns.EVENT_PLACEMENT_UNDERWATER_MWG.getRequirement()), + new ChoiceParameter.Choice<>("wgs", WingShape.image(WingDesign.WGS), false, () -> RewardDesigns.EVENT_PLACEMENT_WARGEAR_SEASON_2022.getRequirement()), + new ChoiceParameter.Choice<>("sword_crossed", WingShape.image(WingDesign.SWORD_CROSSED), false, () -> RewardDesigns.EVENT_PLACEMENT_WARGEAR_CLASH.getRequirement()), new ChoiceParameter.Choice<>("eclipse", WingShape.image(WingDesign.ECLIPSE), true), new ChoiceParameter.Choice<>("pl", WingShape.image(WingDesign.PL), true), new ChoiceParameter.Choice<>("plompa_easter", WingShape.image(WingDesign.PlompaEasterWings), true), diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java b/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java index 6e012ab0..78b10de8 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/EntryParameters.java @@ -132,7 +132,7 @@ public class EntryParameters { } } - public final ChoiceParameter PARTICLE = ChoiceParameter.ofEnum("particle", "PARTICLE_PARAM_PARTICLE", ParticleType.FLAME, type -> !type.isBuildable()); + public final ChoiceParameter PARTICLE = ChoiceParameter.ofEnum("particle", "PARTICLE_PARAM_PARTICLE", ParticleType.FLAME, type -> !type.isBuildable(), ParticleType::getRequirement); public final IntParameter COUNT = new IntParameter("count", "PARTICLE_PARAM_COUNT", 5, 1, 20); // Minecraft scatters particles around their point by about this many blocks; beyond half a block a design dissolves public final DoubleParameter SPREAD_X = new DoubleParameter("spreadX", "PARTICLE_PARAM_SPREAD_X", 0, 0, 0.5, 0.01); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java index 4a4945e1..de64fe61 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/design/ParticleType.java @@ -53,7 +53,7 @@ public enum ParticleType { SMOKE(Material.COBWEB, Particle.SMOKE, Data.NONE, true), LARGE_SMOKE(Material.GRAY_WOOL, Particle.LARGE_SMOKE, Data.NONE, false), WHITE_SMOKE(Material.LIGHT_GRAY_DYE, Particle.WHITE_SMOKE, Data.NONE, true), - CAMPFIRE_COSY_SMOKE(Material.CAMPFIRE, Particle.CAMPFIRE_COSY_SMOKE, Data.NONE, false), + CAMPFIRE_COSY_SMOKE(Material.CAMPFIRE, Particle.CAMPFIRE_COSY_SMOKE, Data.NONE, true), CAMPFIRE_SIGNAL_SMOKE(Material.HAY_BLOCK, Particle.CAMPFIRE_SIGNAL_SMOKE, Data.NONE, false), ASH(Material.BASALT, Particle.ASH, Data.NONE, true), WHITE_ASH(Material.BONE_MEAL, Particle.WHITE_ASH, Data.NONE, true), @@ -180,10 +180,12 @@ public enum ParticleType { return data == Data.DUST || data == Data.COLOR || data == Data.COLOR_TRANSITION || data == Data.TRAIL; } - // Leaves drift down slowly and pile up around a player, so only the server team may build with them + // Leaves drift down slowly and pile up around a player, so only the server team may build with them. Cosy smoke is + // earned by taking part in Hells Bells. public ParticleRequirement getRequirement() { return switch (this) { case CHERRY_LEAVES, PALE_OAK_LEAVES, TINTED_LEAVES -> ParticleRequirement.SERVER_TEAM; + case CAMPFIRE_COSY_SMOKE -> RewardDesigns.EVENT_PARTICIPATION_HELLS_BELLS.getRequirement(); default -> ParticleRequirement.NO_REQUIRMENT; }; } diff --git a/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java b/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java index 0e98a990..c0b5db17 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/gui/EntryEditor.java @@ -22,7 +22,6 @@ package de.steamwar.lobby.particle.gui; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import de.steamwar.lobby.LobbySystem; -import de.steamwar.lobby.particle.ParticleRequirement; import de.steamwar.lobby.particle.UnlockContext; import de.steamwar.lobby.particle.design.*; import de.steamwar.lobby.particle.slot.ParticleEntry; @@ -233,16 +232,19 @@ class EntryEditor { return lines; } - // Left click moves forward, right click backward + // Left click moves forward, right click backward, skipping locked options private void cycle(Context context, ChoiceParameter parameter, E current, int direction) { - List values = parameter.getBuildableValues(); + UnlockContext unlock = new UnlockContext(SteamwarUser.get(context.player().getUniqueId())); + List values = parameter.getBuildableValues().stream() + .filter(value -> value == current || parameter.requirement(value).test(unlock)) + .toList(); apply(context, parameter, values.get(Math.floorMod(values.indexOf(current) + direction, values.size()))); context.reopen(); } private void pick(Context context, ChoiceParameter parameter, E current) { Pickers.choice(context.player(), parameter, current, EntryEditor::choiceIcon, - value -> value instanceof ParticleType type ? type.getRequirement() : ParticleRequirement.NO_REQUIRMENT, picked -> { + parameter::requirement, picked -> { apply(context, parameter, picked); context.reopen(); }, context::reopen); diff --git a/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java b/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java index 12f3be23..11664735 100644 --- a/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java +++ b/LobbySystem/src/de/steamwar/lobby/particle/slot/ParticleEntry.java @@ -175,12 +175,18 @@ public class ParticleEntry { return new Always(values.get(VISIBILITY).wrap(touch)); } - // Shown only when both the design and, for designs that use it, the particle type are unlocked + // Shown only when the design, its chosen options and, for designs that use it, the particle type are unlocked + @SuppressWarnings("unchecked") public boolean isUnlocked(UnlockContext context) { if (!design.getRequirement().test(context)) { return false; } - return !design.usesEntryParticle() || values.get(PARTICLE).getRequirement().test(context); + for (Parameter parameter : design.getParameters()) { + if (parameter instanceof ChoiceParameter choice && !((ChoiceParameter) choice).requirement(values.get(choice)).test(context)) { + return false; + } + } + return !design.usesEntryParticle() || PARTICLE.requirement(values.get(PARTICLE)).test(context); } // Particles each point spawns; designs that set their own point count replace the amount with 1