forked from SteamWar/SteamWar
Improve Advancements performance
This commit is contained in:
@@ -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<SteamwarUser, Map<Advancement.Value.Key, Advancement.Value>> values = new HashMap<>();
|
||||
|
||||
{
|
||||
Advancements.all.add(this);
|
||||
}
|
||||
|
||||
protected final Map<SteamwarUser, Advancement.Data> data = new HashMap<>();
|
||||
protected final Map<SteamwarUser, Advancement.Value> 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<T extends Number> {
|
||||
|
||||
@AllArgsConstructor
|
||||
public static class Key<T extends Number> {
|
||||
public static final List<Key> keys = new ArrayList<>();
|
||||
|
||||
{
|
||||
keys.add(this);
|
||||
}
|
||||
|
||||
private final Function<SteamwarUser, T> valueFunction;
|
||||
|
||||
public T get(SteamwarUser user) {
|
||||
return valueFunction.apply(user);
|
||||
}
|
||||
|
||||
public Function<SteamwarUser, Integer> 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<SteamwarUser, Integer> 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<T> key) {
|
||||
this.value = key.valueFunction.apply(user);
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
public static class Data {
|
||||
private final Advancement advancement;
|
||||
|
||||
@@ -42,6 +42,65 @@ public class Advancements {
|
||||
@Getter
|
||||
private static final List<Advancement> playtime = new ArrayList<>();
|
||||
|
||||
public static final Advancement.Value.Key<Double> 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<Long> FIGHT_COUNT = new Advancement.Value.Key<>(user -> {
|
||||
return FightPlayer.countFights(user.getId());
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Integer> FIGHT_COUNT_WAR_GEAR = new Advancement.Value.Key<>(user -> {
|
||||
return FightPlayer.countFights(user.getId(), "WarGear");
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Integer> FIGHT_COUNT_MINI_WAR_GEAR = new Advancement.Value.Key<>(user -> {
|
||||
return FightPlayer.countFights(user.getId(), "MiniWarGear");
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Integer> FIGHT_COUNT_WAR_SHIP = new Advancement.Value.Key<>(user -> {
|
||||
return FightPlayer.countFights(user.getId(), "WarShip");
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Long> EVENT_FIGHT_COUNT = new Advancement.Value.Key<>(user -> {
|
||||
return EventFight.countEventFights(user);
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Integer> EVENT_FIGHT_FIRST_PLACE_COUNT = new Advancement.Value.Key<>(user -> {
|
||||
return EventFight.countPlacement(user, 1);
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Integer> EVENT_FIGHT_SECOND_PLACE_COUNT = new Advancement.Value.Key<>(user -> {
|
||||
return EventFight.countPlacement(user, 2);
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Integer> EVENT_FIGHT_THIRDPLACE_COUNT = new Advancement.Value.Key<>(user -> {
|
||||
return EventFight.countPlacement(user, 3);
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Long> CHECKED_SCHEMATIC_COUNT = new Advancement.Value.Key<>(user -> {
|
||||
return CheckedSchematic.countChecked(user);
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Long> ACCEPTED_SCHEMATIC_COUNT = new Advancement.Value.Key<>(user -> {
|
||||
return CheckedSchematic.countAccepted(user);
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Long> ACCEPTED_SCHEMATIC_COUNT_WAR_GEAR = new Advancement.Value.Key<>(user -> {
|
||||
return CheckedSchematic.countAccepted(user, "WarGear");
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Long> ACCEPTED_SCHEMATIC_COUNT_MINI_WAR_GEAR = new Advancement.Value.Key<>(user -> {
|
||||
return CheckedSchematic.countAccepted(user, "MiniWarGear");
|
||||
});
|
||||
|
||||
public static final Advancement.Value.Key<Long> 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<Integer> 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<Integer> 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<Long> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Class<? extends MinecraftPacket>> 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<Class<? extends MinecraftPacket>> 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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user