Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbf1d6a798 | ||
|
|
5f6a28fd4d | ||
|
|
312596b2dd | ||
|
|
44858ccb98 | ||
|
|
e1e0908ef1 | ||
|
|
52c904d896 | ||
|
|
24f6670203 | ||
|
|
d0f9791b20 | ||
|
|
f04d2c3260 | ||
|
|
ba9070eddd | ||
|
|
859d901d9a | ||
|
|
9ceca5f7b3 |
No files matched your search
+7
-4
@@ -58,13 +58,16 @@ dependencies {
|
||||
|
||||
// MQTT
|
||||
implementation("org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5")
|
||||
include("org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5")
|
||||
implementation("org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5")
|
||||
|
||||
// JSON
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.20.0")
|
||||
include("com.fasterxml.jackson.core:jackson-databind:2.20.0")
|
||||
include("com.fasterxml.jackson.core:jackson-core:2.20.0")
|
||||
include("com.fasterxml.jackson.core:jackson-annotations:2.20")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.20.0")
|
||||
implementation("com.fasterxml.jackson.core:jackson-core:2.20.0")
|
||||
implementation("com.fasterxml.jackson.core:jackson-annotations:2.20")
|
||||
|
||||
// Hashing
|
||||
implementation("de.mkammerer:argon2-jvm:2.12")
|
||||
}
|
||||
java {
|
||||
toolchain {
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ org.gradle.warning.mode = all
|
||||
org.gradle.configuration-cache = false
|
||||
##########################################################################
|
||||
# Mod Properties
|
||||
mod_version = 1.0.0
|
||||
mod_version = 0.1.1
|
||||
mod_group = ciomek
|
||||
mod_name = loon
|
||||
##########################################################################
|
||||
|
||||
@@ -2,6 +2,7 @@ package ciomek.loon;
|
||||
|
||||
import ciomek.loon.commands.ChangePasswordCommand;
|
||||
import ciomek.loon.commands.RegisterCommand;
|
||||
import ciomek.loon.commands.WebUsernameCommand;
|
||||
import ciomek.loon.mqtt.MQTTClient;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.minecraft.core.net.command.CommandManager;
|
||||
@@ -25,6 +26,7 @@ public class Loon implements ModInitializer {
|
||||
|
||||
CommandManager.registerCommand(new RegisterCommand());
|
||||
CommandManager.registerCommand(new ChangePasswordCommand());
|
||||
CommandManager.registerCommand(new WebUsernameCommand());
|
||||
|
||||
MQTTClient.getInstance();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package ciomek.loon.commands;
|
||||
import ciomek.loon.mqtt.MQTTClient;
|
||||
import ciomek.loon.mqtt.payload.ChangePasswordPayload;
|
||||
import ciomek.loon.mqtt.payload.RegisterResponse;
|
||||
import ciomek.loon.utils.PasswordHasher;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.ArgumentTypeString;
|
||||
@@ -32,18 +33,11 @@ public class ChangePasswordCommand implements CommandManager.CommandRegistry {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String password = ArgumentTypeString.getString(context, "password");
|
||||
String uuid = player.uuid.toString();
|
||||
String responseTopic = "loon/auth/change_password/" + uuid + "/response";
|
||||
|
||||
ChangePasswordPayload payload = new ChangePasswordPayload(player.uuid.toString(), password);
|
||||
|
||||
MQTTClient.getInstance().publish(payload.topics().get(0), payload.toJson());
|
||||
|
||||
source.sendMessage("Sent request to the server! Waiting for the response. ");
|
||||
|
||||
MQTTClient.getInstance().subscribe("loon/register/+/response", (topic, message) -> {
|
||||
String[] parts = topic.split("/");
|
||||
|
||||
String playerUuid = parts[2];
|
||||
MQTTClient.getInstance().subscribe(responseTopic, (topic, message) -> {
|
||||
MQTTClient.getInstance().unsubscribe(responseTopic);
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
RegisterResponse response = objectMapper.readValue(
|
||||
@@ -64,6 +58,16 @@ public class ChangePasswordCommand implements CommandManager.CommandRegistry {
|
||||
}
|
||||
});
|
||||
|
||||
String password = ArgumentTypeString.getString(context, "password");
|
||||
|
||||
String hashedPassword = PasswordHasher.hash(password);
|
||||
|
||||
ChangePasswordPayload payload = new ChangePasswordPayload(uuid, hashedPassword);
|
||||
|
||||
MQTTClient.getInstance().publish(payload.topics().get(0), payload.toJson());
|
||||
|
||||
source.sendMessage("Sent request to the server! Waiting for the response. ");
|
||||
|
||||
return 1;
|
||||
})
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ package ciomek.loon.commands;
|
||||
import ciomek.loon.mqtt.MQTTClient;
|
||||
import ciomek.loon.mqtt.payload.RegisterPayload;
|
||||
import ciomek.loon.mqtt.payload.RegisterResponse;
|
||||
import ciomek.loon.utils.PasswordHasher;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.ArgumentTypeString;
|
||||
@@ -34,19 +35,11 @@ public class RegisterCommand implements CommandManager.CommandRegistry {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String internalUsername = ArgumentTypeString.getString(context, "internalUsername");
|
||||
String password = ArgumentTypeString.getString(context, "password");
|
||||
String uuid = player.uuid.toString();
|
||||
String responseTopic = "loon/auth/register/" + uuid + "/response";
|
||||
|
||||
RegisterPayload payload = new RegisterPayload(player.uuid.toString(), password, internalUsername);
|
||||
|
||||
MQTTClient.getInstance().publish(payload.topics().get(0), payload.toJson());
|
||||
|
||||
source.sendMessage("Sent request to the server! Waiting for the response. ");
|
||||
|
||||
MQTTClient.getInstance().subscribe("loon/register/+/response", (topic, message) -> {
|
||||
String[] parts = topic.split("/");
|
||||
|
||||
String playerUuid = parts[2];
|
||||
MQTTClient.getInstance().subscribe(responseTopic, (topic, message) -> {
|
||||
MQTTClient.getInstance().unsubscribe(responseTopic);
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
RegisterResponse response = objectMapper.readValue(
|
||||
@@ -67,6 +60,17 @@ public class RegisterCommand implements CommandManager.CommandRegistry {
|
||||
}
|
||||
});
|
||||
|
||||
String internalUsername = ArgumentTypeString.getString(context, "internalUsername");
|
||||
String password = ArgumentTypeString.getString(context, "password");
|
||||
|
||||
String hashedPassword = PasswordHasher.hash(password);
|
||||
|
||||
RegisterPayload payload = new RegisterPayload(uuid, hashedPassword, internalUsername);
|
||||
|
||||
MQTTClient.getInstance().publish(payload.topics().get(0), payload.toJson());
|
||||
|
||||
source.sendMessage("Sent request to the server! Waiting for the response. ");
|
||||
|
||||
return 1;
|
||||
})
|
||||
)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package ciomek.loon.commands;
|
||||
|
||||
import ciomek.loon.mqtt.MQTTClient;
|
||||
import ciomek.loon.mqtt.payload.ShowUsernameResponse;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilderLiteral;
|
||||
import net.minecraft.core.entity.player.Player;
|
||||
import net.minecraft.core.net.command.CommandManager;
|
||||
import net.minecraft.core.net.command.CommandSource;
|
||||
|
||||
import static com.mojang.brigadier.builder.ArgumentBuilderLiteral.literal;
|
||||
|
||||
public class WebUsernameCommand implements CommandManager.CommandRegistry {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void register(CommandDispatcher<CommandSource> commandDispatcher) {
|
||||
commandDispatcher
|
||||
.register(
|
||||
(ArgumentBuilderLiteral<CommandSource>) (Object) literal("web-username")
|
||||
.executes(context -> {
|
||||
CommandSource source = (CommandSource) context.getSource();
|
||||
Player player = source.getSender();
|
||||
|
||||
if (player == null) {
|
||||
source.sendMessage("This command can only be run by a player!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
String uuid = player.uuid.toString();
|
||||
String responseTopic = "loon/auth/show_username/" + uuid + "/response";
|
||||
|
||||
MQTTClient.getInstance().subscribe(responseTopic, (topic, message) -> {
|
||||
MQTTClient.getInstance().unsubscribe(responseTopic);
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
ShowUsernameResponse response = objectMapper.readValue(
|
||||
message.getPayload(),
|
||||
ShowUsernameResponse.class
|
||||
);
|
||||
|
||||
if (response == null)
|
||||
return;
|
||||
|
||||
if (response.success())
|
||||
source.sendMessage(response.internalUsername());
|
||||
else
|
||||
source.sendMessage("You are not registered. Use /register command. ");
|
||||
});
|
||||
|
||||
MQTTClient.getInstance().publish("loon/auth/show_username/" + uuid, "{}");
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public class PacketHandlerServerMQTTMixin {
|
||||
|
||||
@Inject(method = "handleSlashCommand", at = @At("TAIL"))
|
||||
private void onSlashCommand(String command, CallbackInfo ci) {
|
||||
CommandPayload payload = new CommandPayload(command, playerEntity.username);
|
||||
CommandPayload payload = new CommandPayload(sanitizeCommand(command), playerEntity.username);
|
||||
|
||||
payload.send();
|
||||
}
|
||||
@@ -59,4 +59,25 @@ public class PacketHandlerServerMQTTMixin {
|
||||
|
||||
payload.send();
|
||||
}
|
||||
|
||||
private String sanitizeCommand(String command) {
|
||||
String normalized = command.startsWith("/") ? command.substring(1) : command;
|
||||
String[] parts = normalized.split(" ");
|
||||
|
||||
if (parts.length == 0) {
|
||||
return command;
|
||||
}
|
||||
|
||||
if ("register".equals(parts[0]) && parts.length >= 3) {
|
||||
parts[2] = "[REDACTED]";
|
||||
return String.join(" ", parts);
|
||||
}
|
||||
|
||||
if ("change-password".equals(parts[0]) && parts.length >= 2) {
|
||||
parts[1] = "[REDACTED]";
|
||||
return String.join(" ", parts);
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package ciomek.loon.mixin;
|
||||
|
||||
import ciomek.loon.Loon;
|
||||
import ciomek.loon.TPSTracker;
|
||||
import ciomek.loon.mqtt.payload.data.PlayerIdentity;
|
||||
import ciomek.loon.mqtt.payload.data.PositionData;
|
||||
@@ -51,31 +52,9 @@ public class WorldServerMixin {
|
||||
|
||||
@Inject(method = "tick", at = @At("TAIL"))
|
||||
private void onTick(CallbackInfo ci) {
|
||||
WorldServer self = (WorldServer) (Object) this;
|
||||
if (self.dimension == Dimension.OVERWORLD) {
|
||||
long now = System.nanoTime();
|
||||
if (lastTickNanos != 0) {
|
||||
gapSumNanos += now - lastTickNanos;
|
||||
gapTicks++;
|
||||
if (gapSumNanos >= 1_000_000_000L) {
|
||||
TPSTracker.setTPS(Math.min(20.0, gapTicks / (gapSumNanos / 1e9)));
|
||||
gapSumNanos = 0;
|
||||
gapTicks = 0;
|
||||
}
|
||||
}
|
||||
lastTickNanos = now;
|
||||
|
||||
if (++positionCheckTicks >= POSITION_CHECK_INTERVAL_TICKS) {
|
||||
positionCheckTicks = 0;
|
||||
broadcastMovedPlayerPositions();
|
||||
}
|
||||
}
|
||||
|
||||
IRequest request;
|
||||
while ((request = RequestManager.pollRequest()) != null) {
|
||||
IRequest current = request;
|
||||
EXECUTOR.submit(() -> current.handle(mcServer));
|
||||
}
|
||||
countTicks();
|
||||
positionCountdown();
|
||||
handleRequests();
|
||||
}
|
||||
|
||||
@Unique
|
||||
@@ -94,4 +73,52 @@ public class WorldServerMixin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Unique private void countTicks()
|
||||
{
|
||||
WorldServer self = (WorldServer) (Object) this;
|
||||
if (self.dimension == Dimension.OVERWORLD) {
|
||||
long now = System.nanoTime();
|
||||
if (lastTickNanos != 0) {
|
||||
gapSumNanos += now - lastTickNanos;
|
||||
gapTicks++;
|
||||
if (gapSumNanos >= 1_000_000_000L) {
|
||||
TPSTracker.setTPS(Math.min(20.0, gapTicks / (gapSumNanos / 1e9)));
|
||||
gapSumNanos = 0;
|
||||
gapTicks = 0;
|
||||
}
|
||||
}
|
||||
lastTickNanos = now;
|
||||
}
|
||||
}
|
||||
|
||||
@Unique private void positionCountdown()
|
||||
{
|
||||
if (++positionCheckTicks >= POSITION_CHECK_INTERVAL_TICKS) {
|
||||
positionCheckTicks = 0;
|
||||
broadcastMovedPlayerPositions();
|
||||
}
|
||||
}
|
||||
|
||||
@Unique private void handleRequests()
|
||||
{
|
||||
IRequest request;
|
||||
while ((request = RequestManager.pollRequest()) != null) {
|
||||
IRequest current = request;
|
||||
if (current.requireTickThread()) {
|
||||
runRequest(current);
|
||||
} else {
|
||||
EXECUTOR.submit(() -> runRequest(current));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void runRequest(IRequest request) {
|
||||
try {
|
||||
request.handle(mcServer);
|
||||
} catch (Exception e) {
|
||||
Loon.LOGGER.error("Failed to handle request: {}, {}", request.getClass().getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,14 @@ public class MQTTClient {
|
||||
}
|
||||
}
|
||||
|
||||
public void unsubscribe(String topicFilter) {
|
||||
try {
|
||||
client.unsubscribe(topicFilter);
|
||||
} catch (MqttException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void publish(String topic, String message, int qos) {
|
||||
MqttMessage mqttMessage = new MqttMessage(message.getBytes());
|
||||
mqttMessage.setQos(qos);
|
||||
@@ -74,11 +82,31 @@ public class MQTTClient {
|
||||
options.setUserName(username);
|
||||
options.setPassword(password.toCharArray());
|
||||
options.setMaxInflight(10000);
|
||||
options.setAutomaticReconnect(true);
|
||||
|
||||
client.setCallback(new MqttCallbackExtended() {
|
||||
@Override
|
||||
public void connectComplete(boolean reconnect, String serverURI) {
|
||||
try {
|
||||
client.subscribe("loon/player/+/inventory/full/request");
|
||||
client.subscribe("loon/player/+/online/request");
|
||||
client.subscribe("loon/player/+/position/request");
|
||||
client.subscribe("loon/world/chunks/+/+/request");
|
||||
client.subscribe("loon/server/info/request");
|
||||
|
||||
if (reconnect)
|
||||
Loon.LOGGER.info("MQTT reconnected");
|
||||
else
|
||||
Loon.LOGGER.info("MQTT connected");
|
||||
|
||||
} catch (MqttException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
client.setCallback(new MqttCallback() {
|
||||
@Override
|
||||
public void connectionLost(Throwable cause) {
|
||||
|
||||
Loon.LOGGER.warn("MQTT connection lost, reconnecting...", cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,11 +116,11 @@ public class MQTTClient {
|
||||
Matcher matcher = pattern.matcher(topic);
|
||||
|
||||
if (matcher.matches()) {
|
||||
UUID playerId = UUID.fromString(matcher.group(1));
|
||||
UUID playerId = parsePlayerUuid(matcher.group(1));
|
||||
if (playerId == null)
|
||||
return;
|
||||
|
||||
InventoryRequest inventoryRequest = new InventoryRequest(playerId);
|
||||
|
||||
RequestManager.addRequest(inventoryRequest);
|
||||
RequestManager.addRequest(new InventoryRequest(playerId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,11 +129,11 @@ public class MQTTClient {
|
||||
Matcher matcher = pattern.matcher(topic);
|
||||
|
||||
if (matcher.matches()) {
|
||||
UUID playerId = UUID.fromString(matcher.group(1));
|
||||
UUID playerId = parsePlayerUuid(matcher.group(1));
|
||||
if (playerId == null)
|
||||
return;
|
||||
|
||||
PlayerOnlineRequest playerOnlineRequest = new PlayerOnlineRequest(playerId);
|
||||
|
||||
RequestManager.addRequest(playerOnlineRequest);
|
||||
RequestManager.addRequest(new PlayerOnlineRequest(playerId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,11 +142,11 @@ public class MQTTClient {
|
||||
Matcher matcher = pattern.matcher(topic);
|
||||
|
||||
if (matcher.matches()) {
|
||||
UUID playerId = UUID.fromString(matcher.group(1));
|
||||
UUID playerId = parsePlayerUuid(matcher.group(1));
|
||||
if (playerId == null)
|
||||
return;
|
||||
|
||||
PlayerPositionRequest request = new PlayerPositionRequest(playerId);
|
||||
|
||||
RequestManager.addRequest(request);
|
||||
RequestManager.addRequest(new PlayerPositionRequest(playerId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,14 +155,21 @@ public class MQTTClient {
|
||||
|
||||
if (matcher.matches())
|
||||
{
|
||||
int xStart = Integer.parseInt(matcher.group(1));
|
||||
int xEnd = Integer.parseInt(matcher.group(2));
|
||||
int zStart = Integer.parseInt(matcher.group(3));
|
||||
int zEnd = Integer.parseInt(matcher.group(4));
|
||||
try
|
||||
{
|
||||
int xStart = Integer.parseInt(matcher.group(1));
|
||||
int xEnd = Integer.parseInt(matcher.group(2));
|
||||
int zStart = Integer.parseInt(matcher.group(3));
|
||||
int zEnd = Integer.parseInt(matcher.group(4));
|
||||
|
||||
ChunkMapRequest request = new ChunkMapRequest(xStart, xEnd, zStart, zEnd);
|
||||
ChunkMapRequest request = new ChunkMapRequest(xStart, xEnd, zStart, zEnd);
|
||||
|
||||
RequestManager.addRequest(request);
|
||||
RequestManager.addRequest(request);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (topic.equals("loon/server/info/request")) {
|
||||
@@ -149,13 +184,17 @@ public class MQTTClient {
|
||||
});
|
||||
|
||||
client.connect(options);
|
||||
client.subscribe("loon/player/+/inventory/full/request");
|
||||
client.subscribe("loon/player/+/online/request");
|
||||
client.subscribe("loon/player/+/position/request");
|
||||
client.subscribe("loon/world/chunks/+/+/request");
|
||||
client.subscribe("loon/server/info/request");
|
||||
} catch (MqttException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static UUID parsePlayerUuid(String raw) {
|
||||
try {
|
||||
return UUID.fromString(raw);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Loon.LOGGER.warn("Ignoring MQTT request with invalid player UUID: {}", raw);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
package ciomek.loon.mqtt.payload;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record ChangePasswordPayload (
|
||||
String uuid,
|
||||
@JsonIgnore String uuid,
|
||||
String password
|
||||
) implements Payload {
|
||||
@Override
|
||||
public List<String> topics() {
|
||||
return List.of("loon/register/change_password");
|
||||
return List.of("loon/auth/register/" + uuid + "/change_password");
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
package ciomek.loon.mqtt.payload;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record RegisterPayload (
|
||||
String uuid,
|
||||
@JsonIgnore String uuid,
|
||||
String password,
|
||||
String internalUsername
|
||||
) implements Payload {
|
||||
@Override
|
||||
public List<String> topics() {
|
||||
return List.of("loon/register/request");
|
||||
return List.of("loon/auth/register/" + uuid + "/request");
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.util.List;
|
||||
public record ServerInfoPayload(
|
||||
double tps,
|
||||
String version,
|
||||
String domain,
|
||||
String motd,
|
||||
boolean onlineMode,
|
||||
int sleepPercentage,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package ciomek.loon.mqtt.payload;
|
||||
|
||||
public record ShowUsernameResponse(
|
||||
boolean success,
|
||||
String error,
|
||||
String internalUsername
|
||||
) {}
|
||||
@@ -19,6 +19,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public record ChunkMapRequest(int xStart, int xEnd, int zStart, int zEnd) implements IRequest {
|
||||
private static final boolean REQUIRE_TICK_THREAD = false;
|
||||
|
||||
@Override
|
||||
public void handle(MinecraftServer server) {
|
||||
World world = server.getDimensionWorld(0);
|
||||
@@ -72,10 +74,11 @@ public record ChunkMapRequest(int xStart, int xEnd, int zStart, int zEnd) implem
|
||||
|
||||
Chunk resolveChunk(World world, ChunkProvider provider, ChunkLoader loader, int x, int z)
|
||||
{
|
||||
ChunkPos chunkPos = new ChunkPos(x, z);
|
||||
|
||||
if (provider.isChunkLoaded(chunkPos))
|
||||
return world.getChunk(chunkPos);
|
||||
if (REQUIRE_TICK_THREAD) {
|
||||
ChunkPos chunkPos = new ChunkPos(x, z);
|
||||
if (provider.isChunkLoaded(chunkPos))
|
||||
return world.getChunk(chunkPos);
|
||||
}
|
||||
|
||||
if (loader == null || !loader.chunkExists(world, x, z))
|
||||
return null;
|
||||
@@ -86,4 +89,10 @@ public record ChunkMapRequest(int xStart, int xEnd, int zStart, int zEnd) implem
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireTickThread()
|
||||
{
|
||||
return REQUIRE_TICK_THREAD;
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,8 @@ import net.minecraft.server.entity.player.PlayerServer;
|
||||
public interface IRequest
|
||||
{
|
||||
void handle(MinecraftServer server);
|
||||
default boolean requireTickThread()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package ciomek.loon.mqtt.request;
|
||||
|
||||
import ciomek.loon.TPSTracker;
|
||||
import ciomek.loon.Loon;
|
||||
import ciomek.loon.mixin.WorldServerMixin;
|
||||
import ciomek.loon.mqtt.payload.ServerInfoPayload;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -8,9 +9,15 @@ import net.minecraft.server.MinecraftServer;
|
||||
public record ServerInfoRequest() implements IRequest {
|
||||
@Override
|
||||
public void handle(MinecraftServer server) {
|
||||
String domain = System.getenv(Loon.EnvVarPrefix + "DOMAIN");
|
||||
if (domain == null) {
|
||||
domain = "";
|
||||
}
|
||||
|
||||
ServerInfoPayload payload = new ServerInfoPayload(
|
||||
TPSTracker.getTPS(),
|
||||
server.getMinecraftVersion(),
|
||||
domain,
|
||||
server.motd,
|
||||
server.onlineMode,
|
||||
server.sleepPercentage,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package ciomek.loon.utils;
|
||||
|
||||
import de.mkammerer.argon2.Argon2Factory;
|
||||
|
||||
public class PasswordHasher {
|
||||
public static String hash(String password) {
|
||||
var argon2 = Argon2Factory.create();
|
||||
return argon2.hash(3, 65536, 1, password.toCharArray());
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
"schemaVersion": 1,
|
||||
"id": "loon",
|
||||
"version": "${version}",
|
||||
"name": "Example Mod",
|
||||
"description": "This mod aims to help new BTA modders.",
|
||||
"name": "loonmc",
|
||||
"description": "Mod that sends data to MQTT server.",
|
||||
"authors": [
|
||||
"Turnip Labs"
|
||||
"ciomek"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "",
|
||||
|
||||
Reference in new issue
Block a user