From a365f708737843a27a54f97f59fe0c8c2e9e3522 Mon Sep 17 00:00:00 2001 From: kento2 Date: Mon, 31 Aug 2026 17:54:57 +0200 Subject: [PATCH] ill try smth --- .../scrow/bukkit/minigame/PlayerManager.java | 8 +- .../bukkit/minigame/lobby/LobbyPhase.java | 5 +- .../lobby/WaitForMaximumPlayersPhase.java | 2 +- .../storable/AbstractStorable.java | 13 ++- .../storable/WrappedStorable.java | 31 ++++--- .../storable/complex/ComplexStorable.java | 10 ++- .../storable/complex/FieldRegistry.java | 1 - .../storable/complex/SubFieldedStorable.java | 24 +++-- .../storable/impl/DurationStorable.java | 23 +++++ .../storable/impl/MiniMessageStorable.java | 25 ++++++ .../impl/location/LocationStorable.java | 3 +- .../impl/location/LocationTeleportAction.java | 6 +- .../storable/impl/world/WorldStorable.java | 4 +- .../{impl => }/list/ListExpandAction.java | 2 +- .../{impl => }/list/ListStorable.java | 41 ++++----- .../storable/primitive/LongStorable.java | 10 +++ .../storable/primitive/PrimitiveStorable.java | 2 +- .../scrow/extraction/ExtractionGame.java | 19 ++++ .../scrow/extraction/ExtractionPlugin.java | 24 ++--- .../extraction/compass/CompassTarget.java | 10 +++ .../compass/CompassTargetRegistry.java | 48 ++++++++++ .../scrow/extraction/config/ArenaConfig.java | 8 +- .../config/ArenaConfigStorable.java | 14 ++- .../extraction/config/ExtractionConfig.java | 26 +++++- .../config/ExtractionPointStorable.java | 19 ++++ .../extractionpoint/ExtractionPoint.java | 32 +++++++ .../extractionpoint/ExtractionProgress.java | 89 +++++++++++++++++++ .../scrow/extraction/phase/MidgamePhase.java | 30 +++++++ 28 files changed, 433 insertions(+), 96 deletions(-) create mode 100644 core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/DurationStorable.java create mode 100644 core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/MiniMessageStorable.java rename core/configurator/main/java/site/lab0x13/scrow/configurator/storable/{impl => }/list/ListExpandAction.java (93%) rename core/configurator/main/java/site/lab0x13/scrow/configurator/storable/{impl => }/list/ListStorable.java (63%) create mode 100644 core/configurator/main/java/site/lab0x13/scrow/configurator/storable/primitive/LongStorable.java create mode 100644 minigame/extraction/site/lab0x13/scrow/extraction/compass/CompassTarget.java create mode 100644 minigame/extraction/site/lab0x13/scrow/extraction/compass/CompassTargetRegistry.java create mode 100644 minigame/extraction/site/lab0x13/scrow/extraction/config/ExtractionPointStorable.java create mode 100644 minigame/extraction/site/lab0x13/scrow/extraction/extractionpoint/ExtractionPoint.java create mode 100644 minigame/extraction/site/lab0x13/scrow/extraction/extractionpoint/ExtractionProgress.java create mode 100644 minigame/extraction/site/lab0x13/scrow/extraction/phase/MidgamePhase.java diff --git a/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/PlayerManager.java b/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/PlayerManager.java index 01b5e05..76fd85f 100644 --- a/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/PlayerManager.java +++ b/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/PlayerManager.java @@ -21,11 +21,11 @@ public final class PlayerManager { this.minigame = minigame; } - public Stream getParticipants() { + public Stream participants() { return participants.stream().map(Bukkit::getPlayer); } - public Stream getSpectators() { + public Stream spectators() { return spectators.stream().map(Bukkit::getPlayer); } @@ -61,7 +61,7 @@ public final class PlayerManager { return spectators.remove(player.getUniqueId()); } - public Stream getAllPlayers() { - return Stream.concat(getParticipants(), getSpectators()); + public Stream allPlayers() { + return Stream.concat(participants(), spectators()); } } diff --git a/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyPhase.java b/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyPhase.java index 806387c..2303fa2 100644 --- a/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyPhase.java +++ b/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/lobby/LobbyPhase.java @@ -33,7 +33,6 @@ public class LobbyPhase extends CompositePhase { ctx.listeners().on(PlayerJoinEvent.class, EventPriority.LOWEST, this::onJoin); ctx.listeners().on(PlayerQuitEvent.class, EventPriority.LOWEST, this::onQuit); - //noinspection unchecked ctx.listeners().cancel( HangingBreakByEntityEvent.class, PlayerInteractAtEntityEvent.class, @@ -51,13 +50,13 @@ public class LobbyPhase extends CompositePhase { private void onJoin(PlayerJoinEvent ev) { ctx.players().addParticipant(ev.getPlayer()); - ctx.players().getAllPlayers().forEach(p -> + ctx.players().allPlayers().forEach(p -> p.sendMessage("§8[§a+§8] §7" + ev.getPlayer().getName())); } private void onQuit(PlayerQuitEvent ev) { if (ctx.players().removeParticipant(ev.getPlayer())) - ctx.players().getAllPlayers().forEach(p -> + ctx.players().allPlayers().forEach(p -> p.sendMessage("§8[§c-§8] §7" + ev.getPlayer().getName())); } diff --git a/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMaximumPlayersPhase.java b/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMaximumPlayersPhase.java index 6caddaf..2289699 100644 --- a/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMaximumPlayersPhase.java +++ b/core/bukkit/api/main/java/de/kentoj/scrow/bukkit/minigame/lobby/WaitForMaximumPlayersPhase.java @@ -30,7 +30,7 @@ class WaitForMaximumPlayersPhase extends Phase { @Override protected void onTick(int tick) { if (tick % 20 == 0) { - ctx.players().getAllPlayers().forEach(player -> + ctx.players().allPlayers().forEach(player -> player.sendTitle("Game starting in " + secsLeft + " seconds", "have fun", 5, 20, 10) ); secsLeft--; diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/AbstractStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/AbstractStorable.java index b057995..be5dc5f 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/AbstractStorable.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/AbstractStorable.java @@ -5,14 +5,23 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; +import java.util.function.Supplier; public abstract class AbstractStorable implements Storable { private final List subscribers = new ArrayList<>(); - @Nullable + private final Supplier defaultValue; protected T value = null; private final List> requirements = new ArrayList<>(); + protected AbstractStorable(Supplier defaultValue) { + this.defaultValue = defaultValue; + } + + protected AbstractStorable(T defaultValue) { + this(() -> defaultValue); + } + protected void requireValue(Predicate predicate, String error) { requirements.add(new ValueRequirement<>(predicate, error)); } @@ -29,7 +38,7 @@ public abstract class AbstractStorable implements Storable { @Override public void value(@Nullable T value) { - this.value = value; + this.value = value != null ? value : defaultValue.get(); subscribers.forEach(ValueChangeSubscriber::notifyValueChange); } diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/WrappedStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/WrappedStorable.java index b27a8ec..17cc467 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/WrappedStorable.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/WrappedStorable.java @@ -4,13 +4,15 @@ import com.google.gson.JsonElement; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.function.Supplier; public abstract class WrappedStorable extends AbstractStorable { private final Storable realStorable; private boolean skipUpdates = false; - public WrappedStorable(Storable realStorable) { + public WrappedStorable(Storable realStorable, Supplier defaultValue) { + super(defaultValue); this.realStorable = realStorable; realStorable.subscribe(() -> { if (realStorable.value() == null) @@ -20,16 +22,25 @@ public abstract class WrappedStorable extends AbstractStorable { }); } + public WrappedStorable(Storable realStorable, T defaultValue) { + this(realStorable, () -> defaultValue); + } + abstract protected T wrap(R real); abstract protected R unwrap(T value); @Override public void value(@Nullable T value) { - if (skipUpdates) - return; super.value(value); - skipUpdates(() -> realStorable.value(value == null ? null : unwrap(value))); + if (skipUpdates) return; + + try { + skipUpdates = true; + realStorable.value(value != null ? unwrap(value) : null); + } finally { + skipUpdates = false; + } } @Override @@ -51,16 +62,4 @@ public abstract class WrappedStorable extends AbstractStorable { public @Nullable Storable getSubField(String name) { return realStorable.getSubField(name); } - - /** - * Run action without updating the value - */ - private void skipUpdates(Action action) { - try { - skipUpdates = true; - action.apply(); - } finally { - skipUpdates = false; - } - } } diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/ComplexStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/ComplexStorable.java index 11bbeb0..c31017d 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/ComplexStorable.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/ComplexStorable.java @@ -2,14 +2,12 @@ package site.lab0x13.scrow.configurator.storable.complex; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import org.jetbrains.annotations.Nullable; import site.lab0x13.scrow.configurator.storable.Storable; public abstract class ComplexStorable extends SubFieldedStorable { - @Override - protected @Nullable T defaultValue() { - return null; + protected ComplexStorable(T defaultValue) { + super(defaultValue); } @Override @@ -24,6 +22,10 @@ public abstract class ComplexStorable extends SubFieldedStorable { @Override public void loadJson(JsonElement json) { + if (json == null) { + value(null); + return; + } var obj = json.getAsJsonObject(); skipUpdates(() -> fieldRegistry().subFields().forEach((subFieldName, subField) -> subField.storable().loadJson(obj.get(subFieldName)))); diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/FieldRegistry.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/FieldRegistry.java index c9e6ffd..aa052be 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/FieldRegistry.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/FieldRegistry.java @@ -11,7 +11,6 @@ public class FieldRegistry { private final Map> subFields = new HashMap<>(); - // TODO move field stuff into own class where register field is one block and after that ready is called public void registerField(String name, Storable storable, Function getter) { subFields.put(name, new Field<>(storable, getter)); } diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/SubFieldedStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/SubFieldedStorable.java index b130914..f4f682f 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/SubFieldedStorable.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/complex/SubFieldedStorable.java @@ -13,7 +13,8 @@ public abstract class SubFieldedStorable extends AbstractStorable { private final FieldRegistry fieldRegistry = new FieldRegistry<>(); private boolean skipUpdates = false; - public SubFieldedStorable() { + public SubFieldedStorable(T defaultValue) { + super(defaultValue); this.registerFields(fieldRegistry); fieldRegistry.subFields().values().forEach(f -> f.storable().subscribe(this::updateValue)); } @@ -22,8 +23,6 @@ public abstract class SubFieldedStorable extends AbstractStorable { protected abstract T construct(FieldReader reader); - protected abstract @Nullable T defaultValue(); - /** * Run action without updating the value */ @@ -44,17 +43,16 @@ public abstract class SubFieldedStorable extends AbstractStorable { @Override public void value(@Nullable T value) { - if (value == null) { - super.value(defaultValue()); - return; - } super.value(value); - - // reflect value change no sub fields - skipUpdates(() -> fieldRegistry.subFields().values().forEach(_field -> { - var field = (Field) _field; - field.storable().value(field.getter().apply(value)); - })); + if (value == null) { + // reset if null + skipUpdates(() -> fieldRegistry.subFields().values().forEach(f -> f.storable().value(null))); + } else { + skipUpdates(() -> fieldRegistry.subFields().values().forEach(_field -> { + var field = (Field) _field; + field.storable().value(field.getter().apply(value)); + })); + } } @Override diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/DurationStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/DurationStorable.java new file mode 100644 index 0000000..6e0b9bc --- /dev/null +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/DurationStorable.java @@ -0,0 +1,23 @@ +package site.lab0x13.scrow.configurator.storable.impl; + +import site.lab0x13.scrow.configurator.storable.complex.ComplexStorable; +import site.lab0x13.scrow.configurator.storable.complex.FieldReader; +import site.lab0x13.scrow.configurator.storable.complex.FieldRegistry; +import site.lab0x13.scrow.configurator.storable.primitive.IntStorable; +import site.lab0x13.scrow.configurator.storable.primitive.LongStorable; + +import java.time.Duration; + +public class DurationStorable extends ComplexStorable { + + @Override + protected void registerFields(FieldRegistry registry) { + registry.registerField("seconds", new LongStorable(), Duration::getSeconds); + registry.registerField("nanos", new IntStorable(), Duration::getNano); + } + + @Override + protected Duration construct(FieldReader reader) { + return Duration.ofSeconds(reader.read("seconds"), reader.read("nanos")); + } +} diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/MiniMessageStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/MiniMessageStorable.java new file mode 100644 index 0000000..e31d22c --- /dev/null +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/MiniMessageStorable.java @@ -0,0 +1,25 @@ +package site.lab0x13.scrow.configurator.storable.impl; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import site.lab0x13.scrow.configurator.storable.WrappedStorable; +import site.lab0x13.scrow.configurator.storable.primitive.StringStorable; + +public class MiniMessageStorable extends WrappedStorable { + + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + + public MiniMessageStorable() { + super(new StringStorable()); + } + + @Override + protected Component wrap(String real) { + return miniMessage.deserialize(real); + } + + @Override + protected String unwrap(Component value) { + return miniMessage.serialize(value); + } +} diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/location/LocationStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/location/LocationStorable.java index 605a0ec..b6051b1 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/location/LocationStorable.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/location/LocationStorable.java @@ -17,7 +17,8 @@ public class LocationStorable extends ComplexStorable { private final List> actions; - public LocationStorable() { + public LocationStorable(Location defaultValue) { + super(defaultValue); actions = new ArrayList<>(super.actions()); actions.add(new LocationPickCurrentAction()); actions.add(new LocationTeleportAction()); diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/location/LocationTeleportAction.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/location/LocationTeleportAction.java index 83109ac..69bf3ba 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/location/LocationTeleportAction.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/location/LocationTeleportAction.java @@ -8,6 +8,9 @@ import site.lab0x13.scrow.configurator.storable.Storable; import java.util.Collections; import java.util.List; +import java.util.Objects; + +import static java.util.Objects.*; class LocationTeleportAction implements StorableAction> { @@ -28,8 +31,7 @@ class LocationTeleportAction implements StorableAction node, ScrowBukkitCC ctx) { - assert node.value() != null; - ctx.player().teleport(node.value()); + ctx.player().teleport(requireNonNull(node.value())); ctx.player().sendMessage(ctx.style().ok("You've been teleported.")); } } diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/world/WorldStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/world/WorldStorable.java index 45737cf..4890fe4 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/world/WorldStorable.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/world/WorldStorable.java @@ -13,8 +13,8 @@ public class WorldStorable extends WrappedStorable { private final List> actions; - public WorldStorable() { - super(new StringStorable()); + public WorldStorable(World defaultValue) { + super(new StringStorable(), defaultValue); actions = new ArrayList<>(super.actions()); actions.add(new SetWorldAction()); } diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/list/ListExpandAction.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/list/ListExpandAction.java similarity index 93% rename from core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/list/ListExpandAction.java rename to core/configurator/main/java/site/lab0x13/scrow/configurator/storable/list/ListExpandAction.java index 3e9678d..0c14f84 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/list/ListExpandAction.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/list/ListExpandAction.java @@ -1,4 +1,4 @@ -package site.lab0x13.scrow.configurator.storable.impl.list; +package site.lab0x13.scrow.configurator.storable.list; import de.kentoj.scrow.bukkit.command.ScrowBukkitCC; import site.lab0x13.scrow.commands.model.argument.Argument; diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/list/ListStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/list/ListStorable.java similarity index 63% rename from core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/list/ListStorable.java rename to core/configurator/main/java/site/lab0x13/scrow/configurator/storable/list/ListStorable.java index bb75a8a..8e7503a 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/impl/list/ListStorable.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/list/ListStorable.java @@ -1,4 +1,4 @@ -package site.lab0x13.scrow.configurator.storable.impl.list; +package site.lab0x13.scrow.configurator.storable.list; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -9,19 +9,21 @@ import site.lab0x13.scrow.configurator.storable.AbstractStorable; import site.lab0x13.scrow.configurator.storable.Storable; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.function.Supplier; import java.util.stream.IntStream; import static java.util.Objects.requireNonNull; -public class ListStorable> extends AbstractStorable> { +public class ListStorable extends AbstractStorable> { - private final Supplier newElementSupplier; + private final Supplier> newElementSupplier; private final List> actions; - public ListStorable(Supplier newElementSupplier) { + private final List> _value = new ArrayList<>(); + + public ListStorable(Supplier> newElementSupplier) { + super(new ArrayList<>()); this.newElementSupplier = newElementSupplier; actions = super.actions(); actions.add(new ListExpandAction<>()); @@ -32,51 +34,42 @@ public class ListStorable> extends AbstractStorable value() { - var v = super.value(); - if (v == null) { - v = new ArrayList<>(); - value(v); - } - return v; - } - /** * Expands the list with a default value storable */ - public S expandList() { + public Storable expandList() { var newElement = newElementSupplier.get(); - requireNonNull(value()).add(newElement); + newElement.subscribe(() -> value(_value.stream().map(Storable::value).toList())); + _value.add(newElement); return newElement; } @Override public JsonElement toJson() { var out = new JsonArray(); - requireNonNull(value()).forEach(storable -> out.add(storable.toJson())); + _value.forEach(storable -> out.add(storable.toJson())); return out; } @Override public void loadJson(JsonElement json) { + if (json == null) { + _value.clear(); + return; + } var in = json.getAsJsonArray(); in.forEach(jsonElement -> expandList().loadJson(jsonElement)); } @Override public List subFieldNames() { - var v = value(); - if (v == null) return Collections.emptyList(); - return IntStream.range(0, v.size()) + return IntStream.range(0, _value.size()) .mapToObj(Integer::toString) .toList(); } @Override public @Nullable Storable getSubField(String name) { - var v = value(); - if (v == null) return null; - return v.get(Integer.parseInt(name)); + return _value.get(Integer.parseInt(name)); } } diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/primitive/LongStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/primitive/LongStorable.java new file mode 100644 index 0000000..141169e --- /dev/null +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/primitive/LongStorable.java @@ -0,0 +1,10 @@ +package site.lab0x13.scrow.configurator.storable.primitive; + +import com.google.gson.JsonPrimitive; + +public class LongStorable extends PrimitiveStorable { + public LongStorable() { + super(0L, JsonPrimitive::new, JsonPrimitive::getAsLong); + } +} + diff --git a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/primitive/PrimitiveStorable.java b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/primitive/PrimitiveStorable.java index a1ee704..dd3512e 100644 --- a/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/primitive/PrimitiveStorable.java +++ b/core/configurator/main/java/site/lab0x13/scrow/configurator/storable/primitive/PrimitiveStorable.java @@ -32,7 +32,7 @@ public class PrimitiveStorable extends AbstractStorable { @Override public void loadJson(JsonElement json) { - if (json.isJsonNull()) + if (json == null || json.isJsonNull()) value(defaultValue); else value(deserializer.apply(json.getAsJsonPrimitive())); diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/ExtractionGame.java b/minigame/extraction/site/lab0x13/scrow/extraction/ExtractionGame.java index 4931ba0..19ec818 100644 --- a/minigame/extraction/site/lab0x13/scrow/extraction/ExtractionGame.java +++ b/minigame/extraction/site/lab0x13/scrow/extraction/ExtractionGame.java @@ -5,15 +5,30 @@ import de.kentoj.scrow.bukkit.minigame.PlayerManager; import de.kentoj.scrow.bukkit.minigame.phaseflow.LinearPhaseFlow; import de.kentoj.scrowlib.convention.ScrowMessageStyle; import net.kyori.adventure.text.format.TextColor; +import site.lab0x13.scrow.extraction.config.ArenaConfig; import java.util.concurrent.CompletableFuture; +/* +While in the network lobby, players select a kit. then when enough players are found, +players are spread on a map and are tasked to extract some tokens. +extracting a token gives you points, items and a temporary health and speed-boost as well as temporary +wallhacks. extracting a token takes a while and other players want to stop you from doing so, so you'll +need to fight. + */ + public class ExtractionGame implements Minigame { private final ScrowMessageStyle style = new ScrowMessageStyle("PotatoRun", TextColor.color(0x8D7726)); private final PlayerManager playerManager = new PlayerManager(this); private final LinearPhaseFlow phaseFlow = new LinearPhaseFlow("potatoRun.root"); + private final ArenaConfig arenaConfig; + + public ExtractionGame(ArenaConfig arenaConfig) { + this.arenaConfig = arenaConfig; + } + @Override public int minParticipants() { return 0; @@ -37,4 +52,8 @@ public class ExtractionGame implements Minigame { public PlayerManager playerManager() { return playerManager; } + + public ArenaConfig arenaConfig() { + return arenaConfig; + } } diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/ExtractionPlugin.java b/minigame/extraction/site/lab0x13/scrow/extraction/ExtractionPlugin.java index 3da0648..ed109c7 100644 --- a/minigame/extraction/site/lab0x13/scrow/extraction/ExtractionPlugin.java +++ b/minigame/extraction/site/lab0x13/scrow/extraction/ExtractionPlugin.java @@ -1,29 +1,23 @@ package site.lab0x13.scrow.extraction; +import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import site.lab0x13.scrow.configurator.configfile.ConfigFile; -import site.lab0x13.scrow.configurator.configfile.ConfigFileRegistry; import site.lab0x13.scrow.extraction.config.ExtractionConfig; -import java.io.IOException; - public class ExtractionPlugin extends JavaPlugin { - private final Logger log = LoggerFactory.getLogger(ExtractionPlugin.class); + private static final Logger log = LoggerFactory.getLogger(ExtractionPlugin.class); + private static Plugin _plugin; + + public static Plugin plugin() { + return _plugin; + } @Override public void onEnable() { - log.info("loading"); - var cfg = ConfigFile.of(this.getDataPath().resolve("config.json")); - ConfigFileRegistry.get().register(cfg); - cfg.registerStorable("arenas", ExtractionConfig.arenas); - try { - cfg.load(); - } catch (IOException e) { - throw new RuntimeException(e); - } - log.info("loaded"); + _plugin = this; + ExtractionConfig.registerAndLoad(this); } } \ No newline at end of file diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/compass/CompassTarget.java b/minigame/extraction/site/lab0x13/scrow/extraction/compass/CompassTarget.java new file mode 100644 index 0000000..bbdb7eb --- /dev/null +++ b/minigame/extraction/site/lab0x13/scrow/extraction/compass/CompassTarget.java @@ -0,0 +1,10 @@ +package site.lab0x13.scrow.extraction.compass; + +import org.bukkit.Location; + +public interface CompassTarget { + + String targetName(); + + Location location(); +} diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/compass/CompassTargetRegistry.java b/minigame/extraction/site/lab0x13/scrow/extraction/compass/CompassTargetRegistry.java new file mode 100644 index 0000000..a6a08d3 --- /dev/null +++ b/minigame/extraction/site/lab0x13/scrow/extraction/compass/CompassTargetRegistry.java @@ -0,0 +1,48 @@ +package site.lab0x13.scrow.extraction.compass; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static com.google.common.base.Preconditions.checkArgument; + +public class CompassTargetRegistry { + + private final Map targets = new HashMap<>(); + + public void targetNearest(Player player, List targetList) { + var nearest = findNearest(player.getLocation(), targetList); + targets.put(player.getUniqueId(), nearest); + } + + public void setCompassTarget(Player player, @Nullable CompassTarget compassTarget) { + if (compassTarget == null) + targets.remove(player.getUniqueId()); + else + targets.put(player.getUniqueId(), compassTarget); + } + + public @Nullable CompassTarget getCompassTarget(Player player) { + return targets.get(player.getUniqueId()); + } + + private static CompassTarget findNearest(Location location, List targetList) { + checkArgument(!targetList.isEmpty(), "targetList is empty"); + + CompassTarget nearest = targetList.getFirst(); + double nearestDistanceSquared = Double.MAX_VALUE; + for (var target : targetList) { + var targetDistanceSquared = target.location().distanceSquared(location); + if (targetDistanceSquared < nearestDistanceSquared) { + nearestDistanceSquared = targetDistanceSquared; + nearest = target; + } + } + return nearest; + } +} diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/config/ArenaConfig.java b/minigame/extraction/site/lab0x13/scrow/extraction/config/ArenaConfig.java index 204961a..ab98810 100644 --- a/minigame/extraction/site/lab0x13/scrow/extraction/config/ArenaConfig.java +++ b/minigame/extraction/site/lab0x13/scrow/extraction/config/ArenaConfig.java @@ -1,11 +1,15 @@ package site.lab0x13.scrow.extraction.config; +import net.kyori.adventure.text.Component; import org.bukkit.Location; -import site.lab0x13.scrow.configurator.storable.Storable; +import site.lab0x13.scrow.extraction.extractionpoint.ExtractionPoint; import java.util.List; public record ArenaConfig( - List> spawnLocations + String id, + Component name, + List spawnLocations, + List extractionPoints ) { } diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/config/ArenaConfigStorable.java b/minigame/extraction/site/lab0x13/scrow/extraction/config/ArenaConfigStorable.java index eb85905..a70f0e7 100644 --- a/minigame/extraction/site/lab0x13/scrow/extraction/config/ArenaConfigStorable.java +++ b/minigame/extraction/site/lab0x13/scrow/extraction/config/ArenaConfigStorable.java @@ -3,18 +3,28 @@ package site.lab0x13.scrow.extraction.config; import site.lab0x13.scrow.configurator.storable.complex.ComplexStorable; import site.lab0x13.scrow.configurator.storable.complex.FieldReader; import site.lab0x13.scrow.configurator.storable.complex.FieldRegistry; -import site.lab0x13.scrow.configurator.storable.impl.list.ListStorable; +import site.lab0x13.scrow.configurator.storable.impl.MiniMessageStorable; +import site.lab0x13.scrow.configurator.storable.list.ListStorable; import site.lab0x13.scrow.configurator.storable.impl.location.LocationStorable; +import site.lab0x13.scrow.configurator.storable.primitive.StringStorable; public class ArenaConfigStorable extends ComplexStorable { @Override protected void registerFields(FieldRegistry registry) { + registry.registerField("id", new StringStorable(), ArenaConfig::id); + registry.registerField("name", new MiniMessageStorable(), ArenaConfig::name); registry.registerField("spawnLocations", new ListStorable<>(LocationStorable::new), ArenaConfig::spawnLocations); + registry.registerField("extractionPoints", new ListStorable<>(ExtractionPointStorable::new), ArenaConfig::extractionPoints); } @Override protected ArenaConfig construct(FieldReader reader) { - return new ArenaConfig(reader.read("spawnLocations")); + return new ArenaConfig( + reader.read("id"), + reader.read("name"), + reader.read("spawnLocations"), + reader.read("extractionPoints") + ); } } diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/config/ExtractionConfig.java b/minigame/extraction/site/lab0x13/scrow/extraction/config/ExtractionConfig.java index b97cda3..95a254b 100644 --- a/minigame/extraction/site/lab0x13/scrow/extraction/config/ExtractionConfig.java +++ b/minigame/extraction/site/lab0x13/scrow/extraction/config/ExtractionConfig.java @@ -1,10 +1,32 @@ package site.lab0x13.scrow.extraction.config; -import site.lab0x13.scrow.configurator.storable.impl.list.ListStorable; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.ApiStatus; +import site.lab0x13.scrow.configurator.configfile.ConfigFile; +import site.lab0x13.scrow.configurator.configfile.ConfigFileRegistry; +import site.lab0x13.scrow.configurator.storable.impl.DurationStorable; +import site.lab0x13.scrow.configurator.storable.list.ListStorable; + +import java.io.IOException; public final class ExtractionConfig { private ExtractionConfig() { } - public static final ListStorable arenas = new ListStorable<>(ArenaConfigStorable::new); + public static final ListStorable arenas = new ListStorable<>(ArenaConfigStorable::new); + public static final DurationStorable extractionDuration = new DurationStorable(); + + public static void registerAndLoad(Plugin plugin) { + var configFile = ConfigFile.of(plugin.getDataPath().resolve("config.json")); + ConfigFileRegistry.get().register(configFile); + { + configFile.registerStorable("arenas", arenas); + configFile.registerStorable("extractionDuration", extractionDuration); + } + try { + configFile.load(); + } catch (IOException e) { + throw new RuntimeException("failed loading config", e); + } + } } diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/config/ExtractionPointStorable.java b/minigame/extraction/site/lab0x13/scrow/extraction/config/ExtractionPointStorable.java new file mode 100644 index 0000000..d77276a --- /dev/null +++ b/minigame/extraction/site/lab0x13/scrow/extraction/config/ExtractionPointStorable.java @@ -0,0 +1,19 @@ +package site.lab0x13.scrow.extraction.config; + +import site.lab0x13.scrow.configurator.storable.complex.ComplexStorable; +import site.lab0x13.scrow.configurator.storable.complex.FieldReader; +import site.lab0x13.scrow.configurator.storable.complex.FieldRegistry; +import site.lab0x13.scrow.configurator.storable.impl.location.LocationStorable; +import site.lab0x13.scrow.extraction.extractionpoint.ExtractionPoint; + +public class ExtractionPointStorable extends ComplexStorable { + @Override + protected void registerFields(FieldRegistry registry) { + registry.registerField("location", new LocationStorable(), ExtractionPoint::location); + } + + @Override + protected ExtractionPoint construct(FieldReader reader) { + return new ExtractionPoint(reader.read("location")); + } +} diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/extractionpoint/ExtractionPoint.java b/minigame/extraction/site/lab0x13/scrow/extraction/extractionpoint/ExtractionPoint.java new file mode 100644 index 0000000..bccd90c --- /dev/null +++ b/minigame/extraction/site/lab0x13/scrow/extraction/extractionpoint/ExtractionPoint.java @@ -0,0 +1,32 @@ +package site.lab0x13.scrow.extraction.extractionpoint; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import site.lab0x13.scrow.extraction.compass.CompassTarget; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public final class ExtractionPoint implements CompassTarget { + private final Location location; + private final Map extractionProgress = new HashMap<>(); + + public ExtractionPoint(Location location) { + this.location = location; + } + + public ExtractionProgress getProgress(Player player) { + return extractionProgress.computeIfAbsent(player.getUniqueId(), _ -> new ExtractionProgress()); + } + + @Override + public String targetName() { + return "Extraction Point"; + } + + @Override + public Location location() { + return location; + } +} diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/extractionpoint/ExtractionProgress.java b/minigame/extraction/site/lab0x13/scrow/extraction/extractionpoint/ExtractionProgress.java new file mode 100644 index 0000000..47757ec --- /dev/null +++ b/minigame/extraction/site/lab0x13/scrow/extraction/extractionpoint/ExtractionProgress.java @@ -0,0 +1,89 @@ +package site.lab0x13.scrow.extraction.extractionpoint; + +import org.bukkit.scheduler.BukkitRunnable; +import site.lab0x13.scrow.extraction.ExtractionPlugin; +import site.lab0x13.scrow.extraction.config.ExtractionConfig; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; + +import static java.util.Objects.requireNonNull; + +/** + * You extract by repeatedly calling {@link ExtractionProgress#advanceExtraction()} + * with little delay in between. + * If the delay is too long, progress is reset. + */ +public class ExtractionProgress { + + /** + * ticks(= 50ms) after which progress will be reset if {@link ExtractionProgress#advanceExtraction()} + * isn't called. + */ + private static final int MAX_DELAY_TICKS = 2; + + private final List> changeSubscribers = new ArrayList<>(); + private final long requiredMs; + /** + * System.currentTimeMillis() at first click (in this attempt to extract) + * or < 0 if extracting hasn't been attempted recently. + */ + private long clickingSince = -1; + /** + * System.currentTimeMillis() at last click + */ + private long lastClickMs = 0; + + /** + * @param extractionTime duration for which progress must be called repeatedly + */ + public ExtractionProgress(Duration extractionTime) { + this.requiredMs = extractionTime.toMillis(); + } + + public ExtractionProgress() { + this(requireNonNull(ExtractionConfig.extractionDuration.value())); + } + + public void advanceExtraction() { + if (clickingSince < 0) + clickingSince = System.currentTimeMillis(); + lastClickMs = System.currentTimeMillis(); + notifyChangeSubscribers(); + + /* reset if not called again for a while */ + new BukkitRunnable() { + final long lastClickMsAtStart = lastClickMs; + @Override + public void run() { + if (lastClickMsAtStart == lastClickMs) + resetProgress(); + } + }.runTaskLater(ExtractionPlugin.plugin(), MAX_DELAY_TICKS); + } + + public double progress() { + if (lastClickMs == 0) + return 0; + var delta = System.currentTimeMillis() - requiredMs; + return Math.max(1.0, (double) delta / (double) requiredMs); + } + + public void resetProgress() { + clickingSince = -1; + lastClickMs = 0; + notifyChangeSubscribers(); + } + + public void subscribeChange(Consumer onChange) { + changeSubscribers.add(onChange); + } + + private void notifyChangeSubscribers() { + var progress = progress(); + changeSubscribers.forEach(sub -> sub.accept(progress)); + } +} diff --git a/minigame/extraction/site/lab0x13/scrow/extraction/phase/MidgamePhase.java b/minigame/extraction/site/lab0x13/scrow/extraction/phase/MidgamePhase.java new file mode 100644 index 0000000..b886677 --- /dev/null +++ b/minigame/extraction/site/lab0x13/scrow/extraction/phase/MidgamePhase.java @@ -0,0 +1,30 @@ +package site.lab0x13.scrow.extraction.phase; + +import de.kentoj.scrow.bukkit.minigame.phase.Phase; +import de.kentoj.scrow.bukkit.minigame.phaseflow.PhaseContext; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import site.lab0x13.scrow.extraction.ExtractionGame; +import site.lab0x13.scrow.extraction.compass.CompassTargetRegistry; + +public class MidgamePhase extends Phase { + + private final CompassTargetRegistry compassTargetRegistry; + + protected MidgamePhase(PhaseContext ctx, CompassTargetRegistry compassTargetRegistry) { + super(ctx); + this.compassTargetRegistry = compassTargetRegistry; + } + + @Override + protected void onStart() { + ctx.players().participants().forEach(player -> { + compassTargetRegistry.targetNearest(player, ctx.game().arenaConfig().extractionPoints()); + player.getInventory().addItem(ItemStack.of(Material.COMPASS)); + }); + } + + @Override + protected void onCancel() { + } +}