diff --git a/VelocityCore/src/de/steamwar/velocitycore/advancements/Advancement.java b/VelocityCore/src/de/steamwar/velocitycore/advancements/Advancement.java index d250ed51..dfbb75b4 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/advancements/Advancement.java +++ b/VelocityCore/src/de/steamwar/velocitycore/advancements/Advancement.java @@ -29,30 +29,32 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder; import de.steamwar.messages.Chatter; +import de.steamwar.sql.EventFight; import de.steamwar.sql.SteamwarUser; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; +import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.ToString; import net.kyori.adventure.text.Component; import java.io.BufferedReader; import java.io.InputStreamReader; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; @RequiredArgsConstructor public class Advancement { + protected static final Map> values = new HashMap<>(); + { Advancements.all.add(this); } protected final Map data = new HashMap<>(); + protected final Map value = new HashMap<>(); public Advancement.Data get(SteamwarUser user) { return get(user, Data::new); @@ -143,6 +145,46 @@ public class Advancement { public abstract boolean hidden(Data data); } + public static class Value { + + @AllArgsConstructor + public static class Key { + public static final List keys = new ArrayList<>(); + + { + keys.add(this); + } + + private final Function valueFunction; + + public T get(SteamwarUser user) { + return valueFunction.apply(user); + } + + public Function max(int neededValue) { + return user -> { + double value = values.get(user).get(Key.this).value.doubleValue(); + if (value > neededValue) return Math.min(neededValue, 100); + return (int) (value / Math.max(neededValue / 100.0, 1)); + }; + } + + public Function reached(int neededValue) { + return user -> { + double value = values.get(user).get(Key.this).value.doubleValue(); + return value >= neededValue ? 1 : 0; + }; + } + } + + @Getter + private T value; + + public void update(SteamwarUser user, Key key) { + this.value = key.valueFunction.apply(user); + } + } + @ToString public static class Data { private final Advancement advancement; diff --git a/VelocityCore/src/de/steamwar/velocitycore/advancements/Advancements.java b/VelocityCore/src/de/steamwar/velocitycore/advancements/Advancements.java index 7b65ef0a..4742d266 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/advancements/Advancements.java +++ b/VelocityCore/src/de/steamwar/velocitycore/advancements/Advancements.java @@ -42,6 +42,65 @@ public class Advancements { @Getter private static final List playtime = new ArrayList<>(); + public static final Advancement.Value.Key PLAY_TIME_KEY = new Advancement.Value.Key<>(user -> { + double playtime = user.getOnlinetime(); + playtime += Instant.now().getEpochSecond() - Storage.sessions.get(Chatter.of(user).getPlayer()).toInstant().getEpochSecond(); + playtime /= 60d * 60d; + return playtime; + }); + + public static final Advancement.Value.Key FIGHT_COUNT = new Advancement.Value.Key<>(user -> { + return FightPlayer.countFights(user.getId()); + }); + + public static final Advancement.Value.Key FIGHT_COUNT_WAR_GEAR = new Advancement.Value.Key<>(user -> { + return FightPlayer.countFights(user.getId(), "WarGear"); + }); + + public static final Advancement.Value.Key FIGHT_COUNT_MINI_WAR_GEAR = new Advancement.Value.Key<>(user -> { + return FightPlayer.countFights(user.getId(), "MiniWarGear"); + }); + + public static final Advancement.Value.Key FIGHT_COUNT_WAR_SHIP = new Advancement.Value.Key<>(user -> { + return FightPlayer.countFights(user.getId(), "WarShip"); + }); + + public static final Advancement.Value.Key EVENT_FIGHT_COUNT = new Advancement.Value.Key<>(user -> { + return EventFight.countEventFights(user); + }); + + public static final Advancement.Value.Key EVENT_FIGHT_FIRST_PLACE_COUNT = new Advancement.Value.Key<>(user -> { + return EventFight.countPlacement(user, 1); + }); + + public static final Advancement.Value.Key EVENT_FIGHT_SECOND_PLACE_COUNT = new Advancement.Value.Key<>(user -> { + return EventFight.countPlacement(user, 2); + }); + + public static final Advancement.Value.Key EVENT_FIGHT_THIRDPLACE_COUNT = new Advancement.Value.Key<>(user -> { + return EventFight.countPlacement(user, 3); + }); + + public static final Advancement.Value.Key CHECKED_SCHEMATIC_COUNT = new Advancement.Value.Key<>(user -> { + return CheckedSchematic.countChecked(user); + }); + + public static final Advancement.Value.Key ACCEPTED_SCHEMATIC_COUNT = new Advancement.Value.Key<>(user -> { + return CheckedSchematic.countAccepted(user); + }); + + public static final Advancement.Value.Key ACCEPTED_SCHEMATIC_COUNT_WAR_GEAR = new Advancement.Value.Key<>(user -> { + return CheckedSchematic.countAccepted(user, "WarGear"); + }); + + public static final Advancement.Value.Key ACCEPTED_SCHEMATIC_COUNT_MINI_WAR_GEAR = new Advancement.Value.Key<>(user -> { + return CheckedSchematic.countAccepted(user, "MiniWarGear"); + }); + + public static final Advancement.Value.Key ACCEPTED_SCHEMATIC_COUNT_WAR_SHIP = new Advancement.Value.Key<>(user -> { + return CheckedSchematic.countAccepted(user, "WarShip"); + }); + public static final Advancement ROOT = new Advancement( "steamwar:advancements/root", Optional.empty(), @@ -77,14 +136,7 @@ public class Advancements { ), Advancement.HidePolicy.PREVIOUS_UNFINISHED, Math.min(neededPlayTime, 100), - user -> { - double playtime = user.getOnlinetime(); - playtime += Instant.now().getEpochSecond() - Storage.sessions.get(Chatter.of(user).getPlayer()).toInstant().getEpochSecond(); - playtime /= 60d * 60d; - - if (playtime > neededPlayTime) return Math.min(neededPlayTime, 100); - return (int) (playtime / Math.max(neededPlayTime / 100.0, 1)); - } + PLAY_TIME_KEY.max(neededPlayTime) ); playtime.add(previous); } @@ -108,22 +160,18 @@ public class Advancements { ), Advancement.HidePolicy.PREVIOUS_UNFINISHED, Math.min(fightCount, 100), - user -> { - long fights = FightPlayer.countFights(user.getId()); - if (fights > fightCount) return Math.min(fightCount, 100); - return (int) (fights / Math.max(fightCount / 100.0, 1)); - } + FIGHT_COUNT.max(fightCount) ); if (i == 0) { - fightsPerType(previous, 5f, "WarGear", "stone_bricks"); - fightsPerType(previous, 6f, "MiniWarGear", "stone_brick_slab"); - fightsPerType(previous, 7f, "WarShip", "dark_oak_boat"); + fightsPerType(previous, 5f, "WarGear", FIGHT_COUNT_WAR_GEAR, "stone_bricks"); + fightsPerType(previous, 6f, "MiniWarGear", FIGHT_COUNT_MINI_WAR_GEAR, "stone_brick_slab"); + fightsPerType(previous, 7f, "WarShip", FIGHT_COUNT_WAR_SHIP, "dark_oak_boat"); } } } - private static void fightsPerType(Advancement previous, float yCoord, String type, String item) { + private static void fightsPerType(Advancement previous, float yCoord, String type, Advancement.Value.Key typeKey, String item) { int[] fightCounts = new int[]{1, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000}; for (int i = 0; i < fightCounts.length; i++) { int fightCount = fightCounts[i]; @@ -140,11 +188,7 @@ public class Advancements { ), i == 0 ? Advancement.HidePolicy.WITH_PREVIOUS : Advancement.HidePolicy.PREVIOUS_UNFINISHED, Math.min(fightCount, 100), - user -> { - long fights = FightPlayer.countFights(user.getId(), type); - if (fights > fightCount) return Math.min(fightCount, 100); - return (int) (fights / Math.max(fightCount / 100.0, 1)); - } + typeKey.max(fightCount) ); } } @@ -167,22 +211,18 @@ public class Advancements { ), Advancement.HidePolicy.PREVIOUS_UNFINISHED, Math.min(eventFightCount, 100), - user -> { - long fights = EventFight.countEventFights(user); - if (fights > eventFightCount) return Math.min(eventFightCount, 100); - return (int) (fights / Math.max(eventFightCount / 100.0, 1)); - } + EVENT_FIGHT_COUNT.max(eventFightCount) ); if (i == 0) { - placementsCounts(previous, 9f, 1, "gold_block", Advancement.Display.FrameType.CHALLENGE); - placementsCounts(previous, 10f, 2, "iron_block", Advancement.Display.FrameType.GOAL); - placementsCounts(previous, 11f, 3, "copper_block", Advancement.Display.FrameType.TASK); + placementsCounts(previous, 9f, 1, "gold_block", EVENT_FIGHT_FIRST_PLACE_COUNT, Advancement.Display.FrameType.CHALLENGE); + placementsCounts(previous, 10f, 2, "iron_block", EVENT_FIGHT_SECOND_PLACE_COUNT, Advancement.Display.FrameType.GOAL); + placementsCounts(previous, 11f, 3, "copper_block", EVENT_FIGHT_THIRDPLACE_COUNT, Advancement.Display.FrameType.TASK); } } } - private static void placementsCounts(Advancement previous, float yCoord, int placement, String item, Advancement.Display.FrameType frameType) { + private static void placementsCounts(Advancement previous, float yCoord, int placement, String item, Advancement.Value.Key typeKey, Advancement.Display.FrameType frameType) { for (int placementCount = 1; placementCount <= 10; placementCount++) { int finalPlacementCount = placementCount; previous = new Advancement( @@ -198,7 +238,7 @@ public class Advancements { ), placementCount == 1 ? Advancement.HidePolicy.WITH_PREVIOUS : Advancement.HidePolicy.PREVIOUS_UNFINISHED, 1, - user -> EventFight.countPlacement(user, placement) >= finalPlacementCount ? 1 : 0 + typeKey.reached(placementCount) ); } } @@ -221,11 +261,7 @@ public class Advancements { ), i == 0 ? Advancement.HidePolicy.NO_PROGRESS : Advancement.HidePolicy.PREVIOUS_UNFINISHED, Math.min(checkedCount, 100), - user -> { - long checked = CheckedSchematic.countChecked(user); - if (checked > checkedCount) return Math.min(checkedCount, 100); - return (int) (checked / Math.max(checkedCount / 100.0, 1)); - } + CHECKED_SCHEMATIC_COUNT.max(checkedCount) ); } } @@ -248,22 +284,18 @@ public class Advancements { ), Advancement.HidePolicy.PREVIOUS_UNFINISHED, Math.min(acceptedCount, 100), - user -> { - long accepted = CheckedSchematic.countAccepted(user); - if (accepted > acceptedCount) return Math.min(acceptedCount, 100); - return (int) (accepted / Math.max(acceptedCount / 100.0, 1)); - } + ACCEPTED_SCHEMATIC_COUNT.max(acceptedCount) ); if (i == 0) { - acceptedPerType(previous, 2f, "WarGear", "end_stone_bricks"); - acceptedPerType(previous, 3f, "MiniWarGear", "end_stone_brick_slab"); - acceptedPerType(previous, 4f, "WarShip", "oak_boat"); + acceptedPerType(previous, 2f, "WarGear", ACCEPTED_SCHEMATIC_COUNT_WAR_GEAR, "end_stone_bricks"); + acceptedPerType(previous, 3f, "MiniWarGear", ACCEPTED_SCHEMATIC_COUNT_MINI_WAR_GEAR, "end_stone_brick_slab"); + acceptedPerType(previous, 4f, "WarShip", ACCEPTED_SCHEMATIC_COUNT_WAR_SHIP, "oak_boat"); } } } - private static void acceptedPerType(Advancement previous, float xCoord, String type, String item) { + private static void acceptedPerType(Advancement previous, float xCoord, String type, Advancement.Value.Key typeKey, String item) { new Advancement( "steamwar:advancements/accepted_" + type, Optional.of(previous), @@ -277,7 +309,7 @@ public class Advancements { ), Advancement.HidePolicy.WITH_PREVIOUS, 1, - user -> CheckedSchematic.countAccepted(user, type) > 0 ? 1 : 0 + typeKey.reached(1) ); } } diff --git a/VelocityCore/src/de/steamwar/velocitycore/advancements/AdvancementsManager.java b/VelocityCore/src/de/steamwar/velocitycore/advancements/AdvancementsManager.java index 9819ce91..0cc6ccf9 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/advancements/AdvancementsManager.java +++ b/VelocityCore/src/de/steamwar/velocitycore/advancements/AdvancementsManager.java @@ -35,6 +35,7 @@ import de.steamwar.velocitycore.listeners.BasicListener; import it.unimi.dsi.fastutil.objects.Object2IntMap; import java.lang.reflect.Field; +import java.util.HashMap; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -46,16 +47,11 @@ public class AdvancementsManager extends BasicListener { static { selectAdvancementTabPacket = new SelectAdvancementTabPacket(Optional.of("steamwar:advancements/root")); - try { - StateRegistry.PacketRegistry.ProtocolRegistry registry = StateRegistry.PLAY.getProtocolRegistry(ProtocolUtils.Direction.CLIENTBOUND, ProtocolVersion.MINECRAFT_1_21_6); - Field field = StateRegistry.PacketRegistry.ProtocolRegistry.class.getDeclaredField("packetClassToId"); - field.setAccessible(true); - Object2IntMap> map = (Object2IntMap) field.get(registry); - map.put(SelectAdvancementTabPacket.class, 0x4E); - map.put(Advancement.Packet.class, 0x7B); - } catch (Exception e) { - // Ignore - } + registerPacketId(ProtocolVersion.MINECRAFT_1_21_9, 0x53, 0x80); + registerPacketId(ProtocolVersion.MINECRAFT_1_21_7, 0x4E, 0x7B); + registerPacketId(ProtocolVersion.MINECRAFT_1_21_6, 0x4E, 0x7B); + registerPacketId(ProtocolVersion.MINECRAFT_1_21_5, 0x4E, 0x7B); + registerPacketId(ProtocolVersion.MINECRAFT_1_21_4, 0x4F, 0x7B); VelocityCore.schedule(() -> { for (Advancement advancement : Advancements.getPlaytime()) { @@ -66,18 +62,44 @@ public class AdvancementsManager extends BasicListener { }).repeat(10, TimeUnit.MINUTES).schedule(); } + private static void registerPacketId(ProtocolVersion version, int selectAdvancementTabPacket, int advancementPacket) { + try { + StateRegistry.PacketRegistry.ProtocolRegistry registry = StateRegistry.PLAY.getProtocolRegistry(ProtocolUtils.Direction.CLIENTBOUND, version); + Field field = StateRegistry.PacketRegistry.ProtocolRegistry.class.getDeclaredField("packetClassToId"); + field.setAccessible(true); + Object2IntMap> map = (Object2IntMap) field.get(registry); + map.put(SelectAdvancementTabPacket.class, selectAdvancementTabPacket); + map.put(Advancement.Packet.class, advancementPacket); + } catch (Exception e) { + // Ignore + } + } + @Subscribe(priority = -1000) public void onPostLogin(PostLoginEvent event) { + // Only enable for 1.21.4 or higher + if (event.getPlayer().getProtocolVersion().lessThan(ProtocolVersion.MINECRAFT_1_21_4)) { + return; + } + ((ConnectedPlayer) event.getPlayer()).getConnection().write(selectAdvancementTabPacket); + SteamwarUser user = SteamwarUser.get(event.getPlayer().getUniqueId()); + Advancement.Value.Key.keys.forEach(key -> { + Advancement.Value value = new Advancement.Value(); + value.update(user, key); + Advancement.values.computeIfAbsent(user, k -> new HashMap<>()).put(key, value); + }); for (Advancement advancement : Advancements.getAll()) { - advancement.get(SteamwarUser.get(event.getPlayer().getUniqueId())); + advancement.get(user); } } @Subscribe public void onDisconnect(DisconnectEvent event) { + SteamwarUser user = SteamwarUser.get(event.getPlayer().getUniqueId()); for (Advancement advancement : Advancements.getAll()) { - advancement.data.remove(SteamwarUser.get(event.getPlayer().getUniqueId())); + advancement.data.remove(user); } + Advancement.values.remove(user); } }