first commit

This commit is contained in:
Lars Behrends
2025-12-28 22:15:00 +01:00
commit 160b1dc341
22 changed files with 1026 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
package ceratic.projectvollidioten;
import net.fabricmc.api.ClientModInitializer;
public class ProjectvollidiotenClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
}
}

View File

@@ -0,0 +1,11 @@
package ceratic.projectvollidioten;
import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
public class ProjectvollidiotenDataGenerator implements DataGeneratorEntrypoint {
@Override
public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
}
}

View File

@@ -0,0 +1,15 @@
package ceratic.projectvollidioten.mixin.client;
import net.minecraft.client.MinecraftClient;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftClient.class)
public class ExampleClientMixin {
@Inject(at = @At("HEAD"), method = "run")
private void init(CallbackInfo info) {
// This code is injected into the start of MinecraftClient.run()V
}
}

View File

@@ -0,0 +1,11 @@
{
"required": true,
"package": "ceratic.projectvollidioten.mixin.client",
"compatibilityLevel": "JAVA_21",
"client": [
"ExampleClientMixin"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -0,0 +1,107 @@
package ceratic.projectvollidioten;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.advancement.AdvancementEntry;
import net.minecraft.advancement.PlayerAdvancementTracker;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Collection;
public class PlayerDataLogger {
public static final Logger LOGGER = LoggerFactory.getLogger("data-logger");
private static final String API_URL = "http://localhost:3000/api/data";
private static final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.connectTimeout(Duration.ofSeconds(5))
.build();
// Gson instance for pretty printing debug output
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static void sendPlayerData(ServerPlayerEntity player, MinecraftServer server, String eventType) {
// 1. Construct the JSON Payload
JsonObject payload = new JsonObject();
// Basic Info & Status
payload.addProperty("eventType", eventType); // JOIN or LEAVE
payload.addProperty("player", player.getName().getString());
payload.addProperty("uuid", player.getUuidAsString());
payload.addProperty("timestamp", System.currentTimeMillis());
// Character Stats
JsonObject stats = new JsonObject();
stats.addProperty("health", player.getHealth());
stats.addProperty("maxHealth", player.getMaxHealth());
stats.addProperty("foodLevel", player.getHungerManager().getFoodLevel());
stats.addProperty("xpLevel", player.experienceLevel);
stats.addProperty("gameMode", player.interactionManager.getGameMode().asString());
JsonObject position = new JsonObject();
position.addProperty("x", player.getX());
position.addProperty("y", player.getY());
position.addProperty("z", player.getZ());
position.addProperty("dimension", player.getWorld().getRegistryKey().getValue().toString());
stats.add("position", position);
payload.add("stats", stats);
// Advancements (Only completed ones with a display)
JsonArray advancementsArray = new JsonArray();
PlayerAdvancementTracker tracker = player.getAdvancementTracker();
// Access the server's advancement loader to iterate all available advancements
Collection<AdvancementEntry> allAdvancements = server.getAdvancementLoader().getAdvancements();
for (AdvancementEntry entry : allAdvancements) {
// Check if advancement has a display (visible) and if player is done
if (entry.value().display().isPresent() && tracker.getProgress(entry).isDone()) {
JsonObject advJson = new JsonObject();
advJson.addProperty("id", entry.id().toString());
advJson.addProperty("title", entry.value().display().get().getTitle().getString());
advancementsArray.add(advJson);
}
}
payload.add("advancements", advancementsArray);
// 2. Convert to String
String jsonString = GSON.toJson(payload);
// 3. DEBUG: Log to Console
LOGGER.info("Preparing to send data to API (Event: {}): \n{}", eventType, jsonString);
// 4. Send to API (Async to prevent server lag)
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(API_URL))
.timeout(Duration.ofSeconds(5))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonString))
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::statusCode)
.thenAccept(status -> {
if (status >= 200 && status < 300) {
LOGGER.info("Successfully sent data for {}. Status: {}", player.getName().getString(), status);
} else {
LOGGER.warn("API returned non-success status: {}", status);
}
})
.exceptionally(e -> {
LOGGER.error("Failed to send data to API: {}", e.getMessage());
return null;
});
}
}

View File

@@ -0,0 +1,35 @@
package ceratic.projectvollidioten;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Projectvollidioten implements ModInitializer {
public static final String MOD_ID = "projectvollidioten";
// This logger is used to write text to the console and the log file.
// It is considered best practice to use your mod id as the logger's name.
// That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
LOGGER.info("Hello Fabric world!");
// Event: Player Join
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
PlayerDataLogger.sendPlayerData(handler.getPlayer(), server, "JOIN");
});
// Event: Player Leave
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
PlayerDataLogger.sendPlayerData(handler.getPlayer(), server, "LEAVE");
});
}
}

View File

@@ -0,0 +1,15 @@
package ceratic.projectvollidioten.mixin;
import net.minecraft.server.MinecraftServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MinecraftServer.class)
public class ExampleMixin {
@Inject(at = @At("HEAD"), method = "loadWorld")
private void init(CallbackInfo info) {
// This code is injected into the start of MinecraftServer.loadWorld()V
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -0,0 +1,41 @@
{
"schemaVersion": 1,
"id": "projectvollidioten",
"version": "${version}",
"name": "projectvollidioten",
"description": "This is an example description! Tell everyone what your mod is about!",
"authors": [
"Me!"
],
"contact": {
"homepage": "https://fabricmc.net/",
"sources": "https://github.com/FabricMC/fabric-example-mod"
},
"license": "CC0-1.0",
"icon": "assets/projectvollidioten/icon.png",
"environment": "*",
"entrypoints": {
"main": [
"ceratic.projectvollidioten.Projectvollidioten"
],
"client": [
"ceratic.projectvollidioten.ProjectvollidiotenClient"
],
"fabric-datagen": [
"ceratic.projectvollidioten.ProjectvollidiotenDataGenerator"
]
},
"mixins": [
"projectvollidioten.mixins.json",
{
"config": "projectvollidioten.client.mixins.json",
"environment": "client"
}
],
"depends": {
"fabricloader": ">=0.18.3",
"minecraft": "~1.21.11",
"java": ">=21",
"fabric-api": "*"
}
}

View File

@@ -0,0 +1,14 @@
{
"required": true,
"package": "ceratic.projectvollidioten.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"ExampleMixin"
],
"injectors": {
"defaultRequire": 1
},
"overwrites": {
"requireAnnotations": true
}
}