@@ -43,7 +42,7 @@ Please provide as much information as you can to best help us understand your is
All of our work is completely free and non-profit (donations pay only for hosting costs), therefore we are very grateful for all donations made to support us in running our community.
Donations can be made via our [website](https://meteorclient.com/donate) and the minimum amount to get donor benefits is €5.
You will be rewarded with a role on our Discord server and a customisable in-game cape.
-⚠️ _Make sure to create a Meteor account and link your Discord and Minecraft accounts to fully experience your rewards._ ⚠️
+⚠️ _Make sure to create a Krypto account and link your Discord and Minecraft accounts to fully experience your rewards._ ⚠️
## Credits
[Cabaletta](https://github.com/cabaletta) and [WagYourTail](https://github.com/wagyourtail) for [Baritone](https://github.com/cabaletta/baritone)
@@ -53,7 +52,7 @@ The [Fabric Team](https://github.com/FabricMC) for [Fabric](https://github.com/F
This project is licensed under the [GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html).
If you use **ANY** code from the source:
-- You must disclose the source code of your modified work and the source code you took from this project. This means you are not allowed to use code from this project (even partially) in a closed-source and/or obfuscated application.
+- You must disclose the source code of your modified work and the source code you took from this project. This means you are not allowed to use code from this project (even partially) in a closed-source application.
- You must state clearly and obviously to all end users that you are using code from this project.
- Your application must also be licensed under the same license.
From 27148757f938593667e8a97bc7471e49d8c13795 Mon Sep 17 00:00:00 2001
From: Casefir <106693177+Casefir@users.noreply.github.com>
Date: Fri, 6 Nov 2026 20:57:52 -0700
Subject: [PATCH 2/7] Clarify README description as upstream fork of Meteor
Client
Updated project description to clarify that this is an upstream fork of Meteor Client.
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 2f5af0bb2c9..4c080844213 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
A Minecraft Fabric Utility Mod for anarchy servers.
A upstream fork of Meteor Client, A Minecraft Fabric Utility Mod for anarchy servers.

From 7fbd8ddd8a1f355136835a1e85f79f8c04813847 Mon Sep 17 00:00:00 2001
From: Casefir <106693177+Casefir@users.noreply.github.com>
Date: Sat, 7 Nov 2026 09:13:08 -0700
Subject: [PATCH 3/7] Revise issue tracker link and clean up README
Updated issue tracker link and removed donation section.
---
README.md | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index 4c080844213..b8b91677244 100644
--- a/README.md
+++ b/README.md
@@ -35,15 +35,9 @@ We will review and help with all reasonable pull requests as long as the guideli
- If you need help, check out the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html) for a reference.
## Bugs and Suggestions
-Bug reports and suggestions should be made in this repo's [issue tracker](https://github.com/MeteorDevelopment/meteor-client/issues) using the templates provided.
+Bug reports and suggestions should be made in this repo's [issue tracker](https://github.com/casefir/krypto-client/issues) using the templates provided.
Please provide as much information as you can to best help us understand your issue and give a better chance of it being resolved.
-## Donations
-All of our work is completely free and non-profit (donations pay only for hosting costs), therefore we are very grateful for all donations made to support us in running our community.
-Donations can be made via our [website](https://meteorclient.com/donate) and the minimum amount to get donor benefits is €5.
-You will be rewarded with a role on our Discord server and a customisable in-game cape.
-⚠️ _Make sure to create a Krypto account and link your Discord and Minecraft accounts to fully experience your rewards._ ⚠️
-
## Credits
[Cabaletta](https://github.com/cabaletta) and [WagYourTail](https://github.com/wagyourtail) for [Baritone](https://github.com/cabaletta/baritone)
The [Fabric Team](https://github.com/FabricMC) for [Fabric](https://github.com/FabricMC/fabric-loader) and [Yarn](https://github.com/FabricMC/yarn)
@@ -54,6 +48,6 @@ This project is licensed under the [GNU General Public License v3.0](https://www
If you use **ANY** code from the source:
- You must disclose the source code of your modified work and the source code you took from this project. This means you are not allowed to use code from this project (even partially) in a closed-source application.
- You must state clearly and obviously to all end users that you are using code from this project.
-- Your application must also be licensed under the same license.
+- Your application must also be licensed under the same license. [METOR CLIENT](https://github.com/MetorDevelopment/)
-*If you have any other questions, check our [FAQ](https://meteorclient.com/faq) or ask in our [Discord](https://meteorclient.com/discord) server.*
+*If you have any other questions, check our [FAQ](https://meteorclient.com/faq)*
From 57ed454253aeb316c4b93a1c59886901a3a4d0a9 Mon Sep 17 00:00:00 2001
From: Casefir <106693177+Casefir@users.noreply.github.com>
Date: Sat, 7 Nov 2026 09:56:32 -0700
Subject: [PATCH 4/7] Add client-side player load notifier module
---
.../meteorclient/systems/modules/Modules.java | 1 +
.../modules/misc/PlayerLoadNotifier.java | 25 +++++++++++++++++++
2 files changed, 26 insertions(+)
create mode 100644 src/main/java/meteordevelopment/meteorclient/systems/modules/misc/PlayerLoadNotifier.java
diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java
index 99cdcb14e2b..3e0fffc806d 100644
--- a/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java
+++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java
@@ -589,6 +589,7 @@ private void initMisc() {
add(new Notifier());
add(new PacketCanceller());
add(new PacketLogger());
+ add(new PlayerLoadNotifier());
add(new ServerSpoof());
add(new SoundBlocker());
add(new Spam());
diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/PlayerLoadNotifier.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/PlayerLoadNotifier.java
new file mode 100644
index 00000000000..55c253c4c36
--- /dev/null
+++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/PlayerLoadNotifier.java
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client).
+ * Copyright (c) Meteor Development.
+ */
+
+package meteordevelopment.meteorclient.systems.modules.misc;
+
+import meteordevelopment.meteorclient.events.entity.EntityAddedEvent;
+import meteordevelopment.meteorclient.systems.modules.Categories;
+import meteordevelopment.meteorclient.systems.modules.Module;
+import meteordevelopment.orbit.EventHandler;
+import net.minecraft.world.entity.player.Player;
+
+public class PlayerLoadNotifier extends Module {
+ public PlayerLoadNotifier() {
+ super(Categories.Misc, "player-load-notifier", "Notifies you when another player loads into your client world.");
+ }
+
+ @EventHandler
+ private void onEntityAdded(EntityAddedEvent event) {
+ if (!(event.entity instanceof Player player) || mc.player == null || player == mc.player) return;
+
+ info("%s loaded.", player.getName().getString());
+ }
+}
From 01d721800b8c289d48aa09051a8da05f0173a680 Mon Sep 17 00:00:00 2001
From: Casefir <106693177+Casefir@users.noreply.github.com>
Date: Sat, 7 Nov 2026 13:28:00 -0700
Subject: [PATCH 5/7] Remove badges and Discord link from README
Removed shield images and Discord link from README.
---
README.md | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/README.md b/README.md
index b8b91677244..f69a028ff18 100644
--- a/README.md
+++ b/README.md
@@ -5,17 +5,6 @@
Krypto
A upstream fork of Meteor Client, A Minecraft Fabric Utility Mod for anarchy servers.
-
-
## Usage
### Building
From f61539c0e5c93dd0bfe3a8027042484012495ece Mon Sep 17 00:00:00 2001
From: Casefir <106693177+Casefir@users.noreply.github.com>
Date: Sun, 8 Nov 2026 15:27:01 -0700
Subject: [PATCH 6/7] Add persistent player history and search command
---
.../meteorclient/commands/Commands.java | 1 +
.../commands/PlayerHistoryCommand.java | 68 ++++++
.../meteorclient/systems/Systems.java | 2 +
.../systems/playerhistory/PlayerHistory.java | 204 ++++++++++++++++++
4 files changed, 275 insertions(+)
create mode 100644 src/main/java/meteordevelopment/meteorclient/commands/commands/PlayerHistoryCommand.java
create mode 100644 src/main/java/meteordevelopment/meteorclient/systems/playerhistory/PlayerHistory.java
diff --git a/src/main/java/meteordevelopment/meteorclient/commands/Commands.java b/src/main/java/meteordevelopment/meteorclient/commands/Commands.java
index f5e2d99451e..350af807915 100644
--- a/src/main/java/meteordevelopment/meteorclient/commands/Commands.java
+++ b/src/main/java/meteordevelopment/meteorclient/commands/Commands.java
@@ -60,6 +60,7 @@ public static void init() {
add(new BindsCommand());
add(new GiveCommand());
add(new NameHistoryCommand());
+ add(new PlayerHistoryCommand());
add(new BindCommand());
add(new FovCommand());
add(new RotationCommand());
diff --git a/src/main/java/meteordevelopment/meteorclient/commands/commands/PlayerHistoryCommand.java b/src/main/java/meteordevelopment/meteorclient/commands/commands/PlayerHistoryCommand.java
new file mode 100644
index 00000000000..264b29efd62
--- /dev/null
+++ b/src/main/java/meteordevelopment/meteorclient/commands/commands/PlayerHistoryCommand.java
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client).
+ * Copyright (c) Meteor Development.
+ */
+
+package meteordevelopment.meteorclient.commands.commands;
+
+import com.mojang.brigadier.arguments.StringArgumentType;
+import com.mojang.brigadier.builder.LiteralArgumentBuilder;
+import meteordevelopment.meteorclient.commands.Command;
+import meteordevelopment.meteorclient.systems.playerhistory.PlayerHistory;
+import net.minecraft.client.multiplayer.ClientSuggestionProvider;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+
+public class PlayerHistoryCommand extends Command {
+ private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+ .withZone(ZoneId.systemDefault());
+
+ public PlayerHistoryCommand() {
+ super("player-history", "Searches your locally saved player sightings.", "phistory");
+ }
+
+ @Override
+ public void build(LiteralArgumentBuilder
builder) {
+ builder.then(literal("search")
+ .then(argument("player", StringArgumentType.word()).executes(context -> {
+ String query = StringArgumentType.getString(context, "player");
+ var results = PlayerHistory.get().search(query);
+
+ if (results.isEmpty()) {
+ info("No saved sightings found for %s.", query);
+ return SINGLE_SUCCESS;
+ }
+
+ info("--- Player sightings for %s (latest %d) ---", query, results.size());
+ for (PlayerHistory.Sighting sighting : results) {
+ info("%s: %s at %d, %d, %d in %s; gear: %s",
+ sighting.name,
+ DATE_FORMAT.format(Instant.ofEpochMilli(sighting.timestamp)),
+ sighting.x, sighting.y, sighting.z,
+ sighting.dimension,
+ sighting.gear
+ );
+ }
+ return SINGLE_SUCCESS;
+ }))
+ );
+
+ builder.then(literal("list").executes(_ -> {
+ info("Player history contains %d sightings. Search with %s search .", PlayerHistory.get().size(), this);
+ return SINGLE_SUCCESS;
+ }));
+
+ builder.then(literal("clear").executes(_ -> {
+ PlayerHistory.get().clear();
+ info("Cleared player history for this server.");
+ return SINGLE_SUCCESS;
+ }));
+
+ builder.executes(_ -> {
+ info("Use %s search , %s list, or %s clear.", this, this, this);
+ return SINGLE_SUCCESS;
+ });
+ }
+}
diff --git a/src/main/java/meteordevelopment/meteorclient/systems/Systems.java b/src/main/java/meteordevelopment/meteorclient/systems/Systems.java
index 803d5706b84..1d33ca1b53d 100644
--- a/src/main/java/meteordevelopment/meteorclient/systems/Systems.java
+++ b/src/main/java/meteordevelopment/meteorclient/systems/Systems.java
@@ -14,6 +14,7 @@
import meteordevelopment.meteorclient.systems.hud.Hud;
import meteordevelopment.meteorclient.systems.macros.Macros;
import meteordevelopment.meteorclient.systems.modules.Modules;
+import meteordevelopment.meteorclient.systems.playerhistory.PlayerHistory;
import meteordevelopment.meteorclient.systems.profiles.Profiles;
import meteordevelopment.meteorclient.systems.proxies.Proxies;
import meteordevelopment.meteorclient.systems.waypoints.Waypoints;
@@ -49,6 +50,7 @@ public static void init() {
add(new Friends());
add(new Accounts());
add(new Waypoints());
+ add(new PlayerHistory());
add(new Profiles());
add(new Proxies());
add(new Hud());
diff --git a/src/main/java/meteordevelopment/meteorclient/systems/playerhistory/PlayerHistory.java b/src/main/java/meteordevelopment/meteorclient/systems/playerhistory/PlayerHistory.java
new file mode 100644
index 00000000000..80abe7c7d89
--- /dev/null
+++ b/src/main/java/meteordevelopment/meteorclient/systems/playerhistory/PlayerHistory.java
@@ -0,0 +1,204 @@
+/*
+ * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client).
+ * Copyright (c) Meteor Development.
+ */
+
+package meteordevelopment.meteorclient.systems.playerhistory;
+
+import meteordevelopment.meteorclient.MeteorClient;
+import meteordevelopment.meteorclient.events.entity.EntityAddedEvent;
+import meteordevelopment.meteorclient.events.game.GameJoinedEvent;
+import meteordevelopment.meteorclient.events.world.TickEvent;
+import meteordevelopment.meteorclient.systems.System;
+import meteordevelopment.meteorclient.systems.Systems;
+import meteordevelopment.meteorclient.utils.Utils;
+import meteordevelopment.orbit.EventHandler;
+import net.minecraft.core.UUIDUtil;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.ListTag;
+import net.minecraft.nbt.Tag;
+import net.minecraft.world.entity.EquipmentSlot;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.ItemStack;
+import org.jspecify.annotations.NonNull;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.UUID;
+
+public class PlayerHistory extends System {
+ private static final long RECORD_INTERVAL_MS = 30_000;
+ private static final int MAX_ENTRIES = 10_000;
+ private static final int MAX_RESULTS = 5;
+
+ private final List sightings = new ArrayList<>();
+ private final java.util.Map lastRecorded = new java.util.HashMap<>();
+ private long nextPeriodicRecord;
+
+ public PlayerHistory() {
+ super(null);
+ }
+
+ public static PlayerHistory get() {
+ return Systems.get(PlayerHistory.class);
+ }
+
+ @EventHandler
+ private void onGameJoined(GameJoinedEvent event) {
+ sightings.clear();
+ lastRecorded.clear();
+ load();
+ nextPeriodicRecord = 0;
+ }
+
+ @EventHandler
+ private void onEntityAdded(EntityAddedEvent event) {
+ if (event.entity instanceof Player player) record(player);
+ }
+
+ @EventHandler
+ private void onTick(TickEvent.Post event) {
+ if (System.currentTimeMillis() < nextPeriodicRecord || mc.level == null) return;
+
+ nextPeriodicRecord = System.currentTimeMillis() + RECORD_INTERVAL_MS;
+ for (Player player : mc.level.players()) record(player);
+ }
+
+ private void record(Player player) {
+ if (mc.player == null || mc.level == null || player == mc.player) return;
+
+ long now = System.currentTimeMillis();
+ Long previous = lastRecorded.get(player.getUUID());
+ if (previous != null && now - previous < RECORD_INTERVAL_MS) return;
+ lastRecorded.put(player.getUUID(), now);
+
+ sightings.add(new Sighting(
+ player.getUUID(),
+ player.getName().getString(),
+ now,
+ mc.level.dimension().identifier().toString(),
+ player.getBlockX(),
+ player.getBlockY(),
+ player.getBlockZ(),
+ getGear(player)
+ ));
+
+ if (sightings.size() > MAX_ENTRIES) sightings.removeFirst();
+ save();
+ }
+
+ private String getGear(Player player) {
+ return "head=" + itemName(player.getItemBySlot(EquipmentSlot.HEAD))
+ + ", chest=" + itemName(player.getItemBySlot(EquipmentSlot.CHEST))
+ + ", legs=" + itemName(player.getItemBySlot(EquipmentSlot.LEGS))
+ + ", feet=" + itemName(player.getItemBySlot(EquipmentSlot.FEET))
+ + ", mainhand=" + itemName(player.getMainHandItem())
+ + ", offhand=" + itemName(player.getOffhandItem());
+ }
+
+ private String itemName(ItemStack stack) {
+ return stack.isEmpty() ? "empty" : stack.getHoverName().getString();
+ }
+
+ public List search(String name) {
+ String query = name.toLowerCase(java.util.Locale.ROOT);
+ return sightings.stream()
+ .filter(sighting -> sighting.name.toLowerCase(java.util.Locale.ROOT).contains(query))
+ .sorted(Comparator.comparingLong((Sighting sighting) -> sighting.timestamp).reversed())
+ .limit(MAX_RESULTS)
+ .toList();
+ }
+
+ public int size() {
+ return sightings.size();
+ }
+
+ public void clear() {
+ sightings.clear();
+ lastRecorded.clear();
+ save();
+ }
+
+ @Override
+ public File getFile() {
+ if (!Utils.canUpdate()) return null;
+ return new File(new File(MeteorClient.FOLDER, "player-history"), Utils.getFileWorldName() + ".nbt");
+ }
+
+ @Override
+ public CompoundTag toTag() {
+ CompoundTag tag = new CompoundTag();
+ ListTag list = new ListTag();
+ for (Sighting sighting : sightings) list.add(sighting.toTag());
+ tag.put("sightings", list);
+ return tag;
+ }
+
+ @Override
+ public PlayerHistory fromTag(CompoundTag tag) {
+ sightings.clear();
+ lastRecorded.clear();
+
+ for (Tag item : tag.getListOrEmpty("sightings")) {
+ if (!(item instanceof CompoundTag sightingTag)) continue;
+ try {
+ Sighting sighting = new Sighting(sightingTag);
+ sightings.add(sighting);
+ lastRecorded.merge(sighting.uuid, sighting.timestamp, Math::max);
+ } catch (IllegalArgumentException ignored) {
+ // Ignore malformed records while preserving the rest of the history.
+ }
+ }
+
+ if (sightings.size() > MAX_ENTRIES) {
+ sightings.subList(0, sightings.size() - MAX_ENTRIES).clear();
+ }
+ return this;
+ }
+
+ public static class Sighting {
+ public final UUID uuid;
+ public final String name;
+ public final long timestamp;
+ public final String dimension;
+ public final int x, y, z;
+ public final String gear;
+
+ private Sighting(UUID uuid, String name, long timestamp, String dimension, int x, int y, int z, String gear) {
+ this.uuid = uuid;
+ this.name = name;
+ this.timestamp = timestamp;
+ this.dimension = dimension;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.gear = gear;
+ }
+
+ private Sighting(CompoundTag tag) {
+ this.uuid = tag.read("uuid", UUIDUtil.CODEC).orElseThrow(() -> new IllegalArgumentException("Missing UUID"));
+ this.name = tag.getStringOr("name", "");
+ this.timestamp = tag.getLongOr("timestamp", 0);
+ this.dimension = tag.getStringOr("dimension", "unknown");
+ this.x = tag.getIntOr("x", 0);
+ this.y = tag.getIntOr("y", 0);
+ this.z = tag.getIntOr("z", 0);
+ this.gear = tag.getStringOr("gear", "unknown");
+ }
+
+ private CompoundTag toTag() {
+ CompoundTag tag = new CompoundTag();
+ tag.store("uuid", UUIDUtil.CODEC, uuid);
+ tag.putString("name", name);
+ tag.putLong("timestamp", timestamp);
+ tag.putString("dimension", dimension);
+ tag.putInt("x", x);
+ tag.putInt("y", y);
+ tag.putInt("z", z);
+ tag.putString("gear", gear);
+ return tag;
+ }
+ }
+}
From 89f57cf5f5ea5249910b2ccfca4da6bdb7cc1050 Mon Sep 17 00:00:00 2001
From: Casefir <106693177+Casefir@users.noreply.github.com>
Date: Sun, 8 Nov 2026 19:09:15 -0700
Subject: [PATCH 7/7] Fix player history Minecraft accessor
---
.../systems/playerhistory/PlayerHistory.java | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/main/java/meteordevelopment/meteorclient/systems/playerhistory/PlayerHistory.java b/src/main/java/meteordevelopment/meteorclient/systems/playerhistory/PlayerHistory.java
index 80abe7c7d89..a991ef49dd0 100644
--- a/src/main/java/meteordevelopment/meteorclient/systems/playerhistory/PlayerHistory.java
+++ b/src/main/java/meteordevelopment/meteorclient/systems/playerhistory/PlayerHistory.java
@@ -20,12 +20,14 @@
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
-import org.jspecify.annotations.NonNull;
import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
+import java.util.Map;
import java.util.UUID;
public class PlayerHistory extends System {
@@ -34,7 +36,7 @@ public class PlayerHistory extends System {
private static final int MAX_RESULTS = 5;
private final List sightings = new ArrayList<>();
- private final java.util.Map lastRecorded = new java.util.HashMap<>();
+ private final Map lastRecorded = new HashMap<>();
private long nextPeriodicRecord;
public PlayerHistory() {
@@ -60,14 +62,14 @@ private void onEntityAdded(EntityAddedEvent event) {
@EventHandler
private void onTick(TickEvent.Post event) {
- if (System.currentTimeMillis() < nextPeriodicRecord || mc.level == null) return;
+ if (System.currentTimeMillis() < nextPeriodicRecord || MeteorClient.mc.level == null) return;
nextPeriodicRecord = System.currentTimeMillis() + RECORD_INTERVAL_MS;
- for (Player player : mc.level.players()) record(player);
+ for (Player player : MeteorClient.mc.level.players()) record(player);
}
private void record(Player player) {
- if (mc.player == null || mc.level == null || player == mc.player) return;
+ if (MeteorClient.mc.player == null || MeteorClient.mc.level == null || player == MeteorClient.mc.player) return;
long now = System.currentTimeMillis();
Long previous = lastRecorded.get(player.getUUID());
@@ -78,7 +80,7 @@ private void record(Player player) {
player.getUUID(),
player.getName().getString(),
now,
- mc.level.dimension().identifier().toString(),
+ MeteorClient.mc.level.dimension().identifier().toString(),
player.getBlockX(),
player.getBlockY(),
player.getBlockZ(),
@@ -103,9 +105,9 @@ private String itemName(ItemStack stack) {
}
public List search(String name) {
- String query = name.toLowerCase(java.util.Locale.ROOT);
+ String query = name.toLowerCase(Locale.ROOT);
return sightings.stream()
- .filter(sighting -> sighting.name.toLowerCase(java.util.Locale.ROOT).contains(query))
+ .filter(sighting -> sighting.name.toLowerCase(Locale.ROOT).contains(query))
.sorted(Comparator.comparingLong((Sighting sighting) -> sighting.timestamp).reversed())
.limit(MAX_RESULTS)
.toList();