Skip to content

Commit

Permalink
Add automatic database seed fetching based on connection string and h…
Browse files Browse the repository at this point in the history
…ashed seed
  • Loading branch information
xpple committed Jan 3, 2025
1 parent 425c01c commit a2d0f97
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 18 deletions.
7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ repositories {
maven { url "https://maven.seedfinding.com/" }
maven { url "https://maven-snapshots.seedfinding.com/" }
maven { url "https://jitpack.io" }
maven { url "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1" }
}

configurations {
Expand Down Expand Up @@ -52,6 +53,10 @@ dependencies {
includedLibrary('com.seedfinding:mc_reversal:ca64c0890c106f1a2207623c316fce86f250b918') { transitive = false }

includedLibrary('com.seedfinding:latticg:1.06')

modRuntimeOnly('me.djtheredstoner:DevAuth-fabric:1.1.0') {
exclude group: 'net.fabricmc', module: 'fabric-loader'
}
}

processResources {
Expand Down Expand Up @@ -95,4 +100,4 @@ publishing {
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
}
}
3 changes: 3 additions & 0 deletions src/main/java/kaptainwutax/seedcrackerX/SeedCracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import kaptainwutax.seedcrackerX.cracker.storage.DataStorage;
import kaptainwutax.seedcrackerX.finder.FinderQueue;
import kaptainwutax.seedcrackerX.init.ClientCommands;
import kaptainwutax.seedcrackerX.util.Database;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.loader.api.FabricLoader;
Expand All @@ -32,6 +33,8 @@ public void onInitialize() {
entrypoints.add(entrypoint.getEntrypoint()));

ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> ClientCommands.registerCommands(dispatcher));

Database.fetchSeeds();
}

public DataStorage getDataStorage() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
package kaptainwutax.seedcrackerX.mixin;

import com.mojang.brigadier.CommandDispatcher;
import kaptainwutax.seedcrackerX.SeedCracker;
import kaptainwutax.seedcrackerX.config.Config;
import kaptainwutax.seedcrackerX.config.StructureSave;
import kaptainwutax.seedcrackerX.cracker.DataAddedEvent;
import kaptainwutax.seedcrackerX.cracker.HashedSeedData;
import kaptainwutax.seedcrackerX.finder.FinderQueue;
import kaptainwutax.seedcrackerX.finder.ReloadFinders;
import kaptainwutax.seedcrackerX.util.Database;
import kaptainwutax.seedcrackerX.util.Log;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.command.CommandSource;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.s2c.play.ChunkDataS2CPacket;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.dimension.DimensionType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
Expand All @@ -29,8 +30,8 @@ public abstract class ClientPlayNetworkHandlerMixin {

@Shadow
private ClientWorld world;
@Shadow
private CommandDispatcher<CommandSource> commandDispatcher;

@Shadow public abstract ClientConnection getConnection();

@Inject(method = "onChunkData", at = @At(value = "TAIL"))
private void onChunkData(ChunkDataS2CPacket packet, CallbackInfo ci) {
Expand All @@ -42,6 +43,7 @@ private void onChunkData(ChunkDataS2CPacket packet, CallbackInfo ci) {
@Inject(method = "onGameJoin", at = @At(value = "TAIL"))
public void onGameJoin(GameJoinS2CPacket packet, CallbackInfo ci) {
newDimension(new HashedSeedData(packet.commonPlayerSpawnInfo().seed()), false);
tryDatabase();
var preloaded = StructureSave.loadStructures();
if (!preloaded.isEmpty()) {
Log.warn("foundRestorableStructures", preloaded.size());
Expand All @@ -51,9 +53,11 @@ public void onGameJoin(GameJoinS2CPacket packet, CallbackInfo ci) {
@Inject(method = "onPlayerRespawn", at = @At(value = "TAIL"))
public void onPlayerRespawn(PlayerRespawnS2CPacket packet, CallbackInfo ci) {
newDimension(new HashedSeedData(packet.commonPlayerSpawnInfo().seed()), true);
tryDatabase();
}

public void newDimension(HashedSeedData hashedSeedData, boolean dimensionChange) {
@Unique
private void newDimension(HashedSeedData hashedSeedData, boolean dimensionChange) {
DimensionType dimension = MinecraftClient.getInstance().world.getDimension();
ReloadFinders.reloadHeight(dimension.minY(), dimension.minY() + dimension.logicalHeight());

Expand All @@ -65,4 +69,12 @@ public void newDimension(HashedSeedData hashedSeedData, boolean dimensionChange)
}
}

@Unique
private void tryDatabase() {
Long seed = Database.getSeed(this.getConnection().getAddress().toString(), SeedCracker.get().getDataStorage().hashedSeedData.getHashedSeed());
if (seed == null) {
return;
}
Log.printSeed("tmachine.foundWorldSeedFromDatabase", seed);
}
}
69 changes: 57 additions & 12 deletions src/main/java/kaptainwutax/seedcrackerX/util/Database.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,32 @@
import kaptainwutax.seedcrackerX.config.Config;
import net.minecraft.client.MinecraftClient;
import net.minecraft.text.Text;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Database {

private static final String DATABASE_POST_URL = "https://script.google.com/macros/s/AKfycbye87L-fEYq2EkgczvhKb_kGecp5wL1oX95vg45TRSwNvpv7K-53zoInGTeI1FZ0kv7DA/exec";
private static final String DATABASE_URL = "https://docs.google.com/spreadsheets/d/1tuQiE-0leW88em9OHbZnH-RFNhVqgoHhIt9WQbeqqWw/export?format=csv&gid=0"; // script link is not updated, this works fine
private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build();
private static final Duration TIMEOUT = Duration.ofSeconds(10);
private static final String SEEDCRACKERX_USER_AGENT = "SeedcrackerX mod";

private static final Map<String, Long> connectionToSeed = new HashMap<>();
private static final Map<Long, Long> hashedSeedToSeed = new HashMap<>();

public static Text joinFakeServerForAuth() {
try {
MinecraftClient client = MinecraftClient.getInstance();
Expand All @@ -39,10 +54,15 @@ public static Text joinFakeServerForAuth() {
return null;
}

public static @Nullable Long getSeed(String connection, long hashedSeed) {
Long seed = connectionToSeed.get(connection);
if (seed != null) {
return seed;
}
return hashedSeedToSeed.get(hashedSeed);
}

public static void handleDatabaseCall(Long seed) {
HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.build();
MinecraftClient client = MinecraftClient.getInstance();
Map<String,Object> data = new HashMap<>();
data.put("serverIp", client.getNetworkHandler().getConnection().getAddress().toString());
Expand All @@ -52,17 +72,16 @@ public static void handleDatabaseCall(Long seed) {
data.put("username", client.player.getName().getString());
data.put("hash", Config.get().anonymusSubmits? 1 : 0);


HttpRequest request = HttpRequest.newBuilder()
.POST(HttpRequest.BodyPublishers.ofString(HttpAuthenticationService.buildQuery(data)))
.uri(URI.create("https://script.google.com/macros/s/AKfycbye87L-fEYq2EkgczvhKb_kGecp5wL1oX95vg45TRSwNvpv7K-53zoInGTeI1FZ0kv7DA/exec"))
.setHeader("User-Agent", "SeedcrackerX mod")
.header("Content-Type", "application/x-www-form-urlencoded")
.build();
HttpRequest request = HttpRequest.newBuilder(URI.create(DATABASE_POST_URL))
.timeout(TIMEOUT)
.POST(HttpRequest.BodyPublishers.ofString(HttpAuthenticationService.buildQuery(data)))
.setHeader(HttpHeaders.USER_AGENT, SEEDCRACKERX_USER_AGENT)
.header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.getMimeType())
.build();

try {
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 302) { //the page says "document moved" but the post gets processed
HttpResponse<String> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == HttpStatus.SC_MOVED_TEMPORARILY) { //the page says "document moved" but the post gets processed
Log.warn("database.success");
} else {
Log.warn("database.fail");
Expand All @@ -71,4 +90,30 @@ public static void handleDatabaseCall(Long seed) {
Log.warn("database.fail");
}
}

public static void fetchSeeds() {
HttpRequest request = HttpRequest.newBuilder(URI.create(DATABASE_URL))
.timeout(TIMEOUT)
.GET()
.setHeader(HttpHeaders.USER_AGENT, SEEDCRACKERX_USER_AGENT)
.build();
HTTP_CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(Database::parseCsv);
}

private static void parseCsv(String csv) {
Arrays.stream(csv.split("\n")).skip(1).forEach(row -> {
try {
String[] seedEntry = row.split(",");
String connection = seedEntry[0];
String seedString = seedEntry[2];
long seed = Long.parseLong(seedString.substring(0, seedString.length() - 1));
connectionToSeed.put(connection, seed);
long hashedSeed = Long.parseLong(seedEntry[6]);
hashedSeedToSeed.put(hashedSeed, seed);
} catch (NumberFormatException | ArrayIndexOutOfBoundsException ignored) {
}
});
}
}
1 change: 1 addition & 0 deletions src/main/resources/assets/seedcrackerx/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"tmachine.decoratorWorldSeedSearch": "Looking for world seeds with decorators...",
"tmachine.hashedSeedWorldSeedSearch": "Looking for world seeds with hashed seed...",
"tmachine.foundWorldSeed": "Found world seed ${SEED}.",
"tmachine.foundWorldSeedFromDatabase": "Found world seed ${SEED} from database.",
"tmachine.worldSeedSearchFinished": "Finished searching for world seeds.",
"tmachine.noResultsRevertingToBiomes": "Finished search with no results, reverting back to biomes.",
"tmachine.moreBiomesNeeded": "You need to collect more biome information",
Expand Down

0 comments on commit a2d0f97

Please sign in to comment.