Merge branch 'fabric' into mongodb
# Conflicts: # src/main/java/org/samo_lego/simpleauth/SimpleAuth.java # src/main/java/org/samo_lego/simpleauth/storage/AuthConfig.java # src/main/java/org/samo_lego/simpleauth/storage/PlayerCache.java
This commit is contained in:
commit
ae8cdd38fd
|
@ -63,5 +63,5 @@ jobs:
|
||||||
# The path to the asset you want to upload
|
# The path to the asset you want to upload
|
||||||
asset_path: build/libs/${{ env.BUILDNAME }}.jar
|
asset_path: build/libs/${{ env.BUILDNAME }}.jar
|
||||||
# The name of the asset you want to upload
|
# The name of the asset you want to upload
|
||||||
asset_name: ${{ env.BUILDNAME }}
|
asset_name: ${{ env.PROJECT_ID }}_fabric-${{ env.VERSION }}-${{ env.MC_VERSION }}.jar
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
|
@ -10,7 +10,7 @@ loader_version=0.9.3+build.207
|
||||||
fabric_version=0.20.2+build.402-1.16
|
fabric_version=0.20.2+build.402-1.16
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version = 1.5.3
|
mod_version = 1.6.0
|
||||||
maven_group = org.samo_lego
|
maven_group = org.samo_lego
|
||||||
archives_base_name = simpleauth
|
archives_base_name = simpleauth
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
import net.fabricmc.fabric.api.event.player.*;
|
import net.fabricmc.fabric.api.event.player.*;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
|
@ -30,17 +29,16 @@ import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.iq80.leveldb.impl.Iq80DBFactory.bytes;
|
import static org.iq80.leveldb.impl.Iq80DBFactory.bytes;
|
||||||
import static org.samo_lego.simpleauth.utils.CarpetHelper.isPlayerCarpetFake;
|
import static org.samo_lego.simpleauth.utils.CarpetHelper.isPlayerCarpetFake;
|
||||||
|
import static org.samo_lego.simpleauth.commands.AuthCommand.reloadConfig;
|
||||||
|
import static org.samo_lego.simpleauth.event.AuthEventHandler.*;
|
||||||
import static org.samo_lego.simpleauth.utils.SimpleLogger.logError;
|
import static org.samo_lego.simpleauth.utils.SimpleLogger.logError;
|
||||||
import static org.samo_lego.simpleauth.utils.SimpleLogger.logInfo;
|
import static org.samo_lego.simpleauth.utils.SimpleLogger.logInfo;
|
||||||
import static org.samo_lego.simpleauth.utils.UuidConverter.convertUuid;
|
|
||||||
|
|
||||||
public class SimpleAuth implements DedicatedServerModInitializer {
|
public class SimpleAuth implements DedicatedServerModInitializer {
|
||||||
|
|
||||||
|
@ -48,27 +46,13 @@ public class SimpleAuth implements DedicatedServerModInitializer {
|
||||||
|
|
||||||
public static final ExecutorService THREADPOOL = Executors.newCachedThreadPool();
|
public static final ExecutorService THREADPOOL = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
private static final Timer TIMER = new Timer();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HashMap of players that have joined the server.
|
* HashMap of players that have joined the server.
|
||||||
* It's cleared on server stop in order to save some interactions with database during runtime.
|
* It's cleared on server stop in order to save some interactions with database during runtime.
|
||||||
* Stores their data as {@link org.samo_lego.simpleauth.storage.PlayerCache PlayerCache} object
|
* Stores their data as {@link org.samo_lego.simpleauth.storage.PlayerCache PlayerCache} object.
|
||||||
*/
|
*/
|
||||||
public static HashMap<String, PlayerCache> playerCacheMap = new HashMap<>();
|
public static HashMap<String, PlayerCache> playerCacheMap = new HashMap<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether player is authenticated.
|
|
||||||
* Fake players always count as authenticated.
|
|
||||||
*
|
|
||||||
* @param player player that needs to be checked
|
|
||||||
* @return false if player is not authenticated, otherwise true
|
|
||||||
*/
|
|
||||||
public static boolean isAuthenticated(ServerPlayerEntity player) {
|
|
||||||
String uuid = convertUuid(player);
|
|
||||||
return playerCacheMap.containsKey(uuid) && playerCacheMap.get(uuid).isAuthenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getting game directory
|
// Getting game directory
|
||||||
public static final Path gameDirectory = FabricLoader.getInstance().getGameDir();
|
public static final Path gameDirectory = FabricLoader.getInstance().getGameDir();
|
||||||
|
|
||||||
|
@ -139,8 +123,6 @@ public class SimpleAuth implements DedicatedServerModInitializer {
|
||||||
// Closing threads
|
// Closing threads
|
||||||
try {
|
try {
|
||||||
THREADPOOL.shutdownNow();
|
THREADPOOL.shutdownNow();
|
||||||
TIMER.cancel();
|
|
||||||
TIMER.purge();
|
|
||||||
if (!THREADPOOL.awaitTermination(100, TimeUnit.MICROSECONDS)) {
|
if (!THREADPOOL.awaitTermination(100, TimeUnit.MICROSECONDS)) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
|
@ -152,156 +134,4 @@ public class SimpleAuth implements DedicatedServerModInitializer {
|
||||||
// Closing DB connection
|
// Closing DB connection
|
||||||
DB.close();
|
DB.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the text which tells the player
|
|
||||||
* to login or register, depending on account status.
|
|
||||||
*
|
|
||||||
* @param player player who will get the message
|
|
||||||
* @return LiteralText with appropriate string (login or register)
|
|
||||||
*/
|
|
||||||
public static LiteralText notAuthenticated(PlayerEntity player) {
|
|
||||||
final PlayerCache cache = playerCacheMap.get(convertUuid(player));
|
|
||||||
if(SimpleAuth.config.main.enableGlobalPassword || cache.isRegistered)
|
|
||||||
return new LiteralText(
|
|
||||||
SimpleAuth.config.lang.notAuthenticated + "\n" + SimpleAuth.config.lang.loginRequired
|
|
||||||
);
|
|
||||||
return new LiteralText(
|
|
||||||
SimpleAuth.config.lang.notAuthenticated+ "\n" + SimpleAuth.config.lang.registerRequired
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticates player and sends the success message.
|
|
||||||
*
|
|
||||||
* @param player player that needs to be authenticated
|
|
||||||
* @param msg message to be send to the player
|
|
||||||
*/
|
|
||||||
public static void authenticatePlayer(ServerPlayerEntity player, Text msg) {
|
|
||||||
PlayerCache playerCache = playerCacheMap.get(convertUuid(player));
|
|
||||||
// Teleporting player back
|
|
||||||
if(config.main.spawnOnJoin)
|
|
||||||
teleportPlayer(player, false);
|
|
||||||
|
|
||||||
// Updating blocks if needed (if portal rescue action happened)
|
|
||||||
if(playerCache.wasInPortal) {
|
|
||||||
World world = player.getEntityWorld();
|
|
||||||
BlockPos pos = player.getBlockPos();
|
|
||||||
|
|
||||||
// Sending updates to portal blocks
|
|
||||||
// This is technically not needed, but it cleans the "messed portal" on the client
|
|
||||||
world.updateListeners(pos, world.getBlockState(pos), world.getBlockState(pos), 3);
|
|
||||||
world.updateListeners(pos.up(), world.getBlockState(pos.up()), world.getBlockState(pos.up()), 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setting last air to player
|
|
||||||
if(player.isSubmergedInWater())
|
|
||||||
player.setAir(playerCache.lastAir);
|
|
||||||
|
|
||||||
// In case player is in lava during authentication proccess
|
|
||||||
if(!playerCache.wasOnFire)
|
|
||||||
player.setFireTicks(0);
|
|
||||||
|
|
||||||
playerCache.isAuthenticated = true;
|
|
||||||
|
|
||||||
// Player no longer needs to be invisible and invulnerable
|
|
||||||
player.setInvulnerable(false);
|
|
||||||
player.setInvisible(false);
|
|
||||||
player.sendMessage(msg, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* De-authenticates the player.
|
|
||||||
*
|
|
||||||
* @param player player that needs to be de-authenticated
|
|
||||||
*/
|
|
||||||
public static void deauthenticatePlayer(ServerPlayerEntity player) {
|
|
||||||
if(DB.isClosed())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Marking player as not authenticated
|
|
||||||
String uuid = convertUuid(player);
|
|
||||||
playerCacheMap.put(uuid, PlayerCache.fromJson(player, DB.getUserData(uuid)));
|
|
||||||
playerCacheMap.get(uuid).isAuthenticated = false;
|
|
||||||
|
|
||||||
// Teleporting player to spawn to hide its position
|
|
||||||
if(config.main.spawnOnJoin)
|
|
||||||
teleportPlayer(player, true);
|
|
||||||
|
|
||||||
// Player is now not authenticated
|
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
|
||||||
|
|
||||||
// Setting the player to be invisible to mobs and also invulnerable
|
|
||||||
player.setInvulnerable(SimpleAuth.config.experimental.playerInvulnerable);
|
|
||||||
player.setInvisible(SimpleAuth.config.experimental.playerInvisible);
|
|
||||||
|
|
||||||
// Kicks player after a certain amount of time if not authenticated
|
|
||||||
TIMER.schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// Kicking player if not authenticated
|
|
||||||
if(!isAuthenticated(player) && player.networkHandler.getConnection().isOpen())
|
|
||||||
player.networkHandler.disconnect(new LiteralText(SimpleAuth.config.lang.timeExpired));
|
|
||||||
}
|
|
||||||
}, SimpleAuth.config.main.kickTime * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether player is a fake player (from CarpetMod).
|
|
||||||
*
|
|
||||||
* @param player player that needs to be checked
|
|
||||||
* @return true if player is fake, otherwise false
|
|
||||||
*/
|
|
||||||
public static boolean isPlayerFake(PlayerEntity player) {
|
|
||||||
// We ask CarpetHelper class since it has the imports needed
|
|
||||||
return FabricLoader.getInstance().isModLoaded("carpet") && isPlayerCarpetFake(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Teleports player to spawn or last location that is recorded.
|
|
||||||
* Last location means the location before de-authentication.
|
|
||||||
*
|
|
||||||
* @param player player that needs to be teleported
|
|
||||||
* @param toSpawn whether to teleport player to spawn (provided in config) or last recorded position
|
|
||||||
*/
|
|
||||||
public static void teleportPlayer(ServerPlayerEntity player, boolean toSpawn) {
|
|
||||||
MinecraftServer server = player.getServer();
|
|
||||||
if(server == null || config.worldSpawn.dimension == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (toSpawn) {
|
|
||||||
// Teleports player to spawn
|
|
||||||
player.teleport(
|
|
||||||
server.getWorld(RegistryKey.of(Registry.DIMENSION, new Identifier(config.worldSpawn.dimension))),
|
|
||||||
config.worldSpawn.x,
|
|
||||||
config.worldSpawn.y,
|
|
||||||
config.worldSpawn.z,
|
|
||||||
90,
|
|
||||||
90
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PlayerCache cache = playerCacheMap.get(convertUuid(player));
|
|
||||||
// Puts player to last cached position
|
|
||||||
try {
|
|
||||||
player.teleport(
|
|
||||||
server.getWorld(RegistryKey.of(Registry.DIMENSION, new Identifier(cache.lastLocation.lastDim))),
|
|
||||||
cache.lastLocation.lastX,
|
|
||||||
cache.lastLocation.lastY,
|
|
||||||
cache.lastLocation.lastZ,
|
|
||||||
cache.lastLocation.lastYaw,
|
|
||||||
cache.lastLocation.lastPitch
|
|
||||||
);
|
|
||||||
} catch (Error e) {
|
|
||||||
player.sendMessage(new LiteralText(config.lang.corruptedPlayerData), false);
|
|
||||||
logError("Couldn't teleport player " + player.getName().asString());
|
|
||||||
logError(
|
|
||||||
String.format("Last recorded position is X: %s, Y: %s, Z: %s in dimension %s",
|
|
||||||
cache.lastLocation.lastX,
|
|
||||||
cache.lastLocation.lastY,
|
|
||||||
cache.lastLocation.lastZ,
|
|
||||||
cache.lastLocation.lastDim
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,14 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import org.samo_lego.simpleauth.SimpleAuth;
|
|
||||||
import org.samo_lego.simpleauth.utils.AuthHelper;
|
import org.samo_lego.simpleauth.utils.AuthHelper;
|
||||||
|
import org.samo_lego.simpleauth.utils.PlayerAuth;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.word;
|
import static com.mojang.brigadier.arguments.StringArgumentType.word;
|
||||||
import static net.minecraft.server.command.CommandManager.argument;
|
import static net.minecraft.server.command.CommandManager.argument;
|
||||||
import static net.minecraft.server.command.CommandManager.literal;
|
import static net.minecraft.server.command.CommandManager.literal;
|
||||||
import static org.samo_lego.simpleauth.SimpleAuth.*;
|
import static org.samo_lego.simpleauth.SimpleAuth.*;
|
||||||
import static org.samo_lego.simpleauth.utils.UuidConverter.convertUuid;
|
|
||||||
|
|
||||||
public class AccountCommand {
|
public class AccountCommand {
|
||||||
|
|
||||||
|
@ -36,7 +35,7 @@ public class AccountCommand {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.then(literal("changePassword")
|
.then(literal("changePassword") //todo mongodb update
|
||||||
.then(argument("old password", word())
|
.then(argument("old password", word())
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
ctx.getSource().getPlayer().sendMessage(
|
ctx.getSource().getPlayer().sendMessage(
|
||||||
|
@ -72,13 +71,10 @@ public class AccountCommand {
|
||||||
|
|
||||||
// Different thread to avoid lag spikes
|
// Different thread to avoid lag spikes
|
||||||
THREADPOOL.submit(() -> {
|
THREADPOOL.submit(() -> {
|
||||||
if (AuthHelper.checkPassword(convertUuid(player), pass.toCharArray()) == 1) {
|
if (AuthHelper.checkPassword(((PlayerAuth) player).getFakeUuid(), pass.toCharArray()) == 1) {
|
||||||
DB.deleteUserData(convertUuid(player));
|
DB.deleteUserData(((PlayerAuth) player).getFakeUuid());
|
||||||
player.sendMessage(
|
player.sendMessage(new LiteralText(config.lang.accountDeleted), false);
|
||||||
new LiteralText(config.lang.accountDeleted),
|
((PlayerAuth) player).setAuthenticated(false);
|
||||||
false
|
|
||||||
);
|
|
||||||
SimpleAuth.deauthenticatePlayer(player);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.sendMessage(
|
player.sendMessage(
|
||||||
|
@ -103,7 +99,7 @@ public class AccountCommand {
|
||||||
}
|
}
|
||||||
// Different thread to avoid lag spikes
|
// Different thread to avoid lag spikes
|
||||||
THREADPOOL.submit(() -> {
|
THREADPOOL.submit(() -> {
|
||||||
if (AuthHelper.checkPassword(convertUuid(player), oldPass.toCharArray()) == 1) {
|
if (AuthHelper.checkPassword(((PlayerAuth) player).getFakeUuid(), oldPass.toCharArray()) == 1) {
|
||||||
if (newPass.length() < config.main.minPasswordChars) {
|
if (newPass.length() < config.main.minPasswordChars) {
|
||||||
player.sendMessage(new LiteralText(
|
player.sendMessage(new LiteralText(
|
||||||
String.format(config.lang.minPasswordChars, config.main.minPasswordChars)
|
String.format(config.lang.minPasswordChars, config.main.minPasswordChars)
|
||||||
|
@ -117,7 +113,7 @@ public class AccountCommand {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Changing password in playercache
|
// Changing password in playercache
|
||||||
playerCacheMap.get(convertUuid(player)).password = AuthHelper.hashPassword(newPass.toCharArray());
|
playerCacheMap.get(((PlayerAuth) player).getFakeUuid()).password = AuthHelper.hashPassword(newPass.toCharArray());
|
||||||
player.sendMessage(
|
player.sendMessage(
|
||||||
new LiteralText(config.lang.passwordUpdated),
|
new LiteralText(config.lang.passwordUpdated),
|
||||||
false
|
false
|
||||||
|
|
|
@ -6,13 +6,13 @@ import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import org.samo_lego.simpleauth.utils.AuthHelper;
|
import org.samo_lego.simpleauth.utils.AuthHelper;
|
||||||
|
import org.samo_lego.simpleauth.utils.PlayerAuth;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.word;
|
import static com.mojang.brigadier.arguments.StringArgumentType.word;
|
||||||
import static net.minecraft.server.command.CommandManager.argument;
|
import static net.minecraft.server.command.CommandManager.argument;
|
||||||
import static net.minecraft.server.command.CommandManager.literal;
|
import static net.minecraft.server.command.CommandManager.literal;
|
||||||
import static org.samo_lego.simpleauth.SimpleAuth.*;
|
import static org.samo_lego.simpleauth.SimpleAuth.*;
|
||||||
import static org.samo_lego.simpleauth.utils.UuidConverter.convertUuid;
|
|
||||||
|
|
||||||
public class LoginCommand {
|
public class LoginCommand {
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ public class LoginCommand {
|
||||||
private static int login(ServerCommandSource source, String pass) throws CommandSyntaxException {
|
private static int login(ServerCommandSource source, String pass) throws CommandSyntaxException {
|
||||||
// Getting the player who send the command
|
// Getting the player who send the command
|
||||||
ServerPlayerEntity player = source.getPlayer();
|
ServerPlayerEntity player = source.getPlayer();
|
||||||
String uuid = convertUuid(player);
|
String uuid = ((PlayerAuth) player).getFakeUuid();
|
||||||
if (isAuthenticated(player)) {
|
if (((PlayerAuth) player).isAuthenticated()) {
|
||||||
player.sendMessage(new LiteralText(config.lang.alreadyAuthenticated), false);
|
player.sendMessage(new LiteralText(config.lang.alreadyAuthenticated), false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,8 @@ public class LoginCommand {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(passwordResult == 1) {
|
else if(passwordResult == 1) {
|
||||||
authenticatePlayer(player, new LiteralText(config.lang.successfullyAuthenticated));
|
player.sendMessage(new LiteralText(config.lang.successfullyAuthenticated), false);
|
||||||
|
((PlayerAuth) player).setAuthenticated(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(passwordResult == -1) {
|
else if(passwordResult == -1) {
|
||||||
|
|
|
@ -5,11 +5,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import org.samo_lego.simpleauth.storage.PlayerCache;
|
import org.samo_lego.simpleauth.utils.PlayerAuth;
|
||||||
|
|
||||||
import static net.minecraft.server.command.CommandManager.literal;
|
import static net.minecraft.server.command.CommandManager.literal;
|
||||||
import static org.samo_lego.simpleauth.SimpleAuth.*;
|
import static org.samo_lego.simpleauth.SimpleAuth.config;
|
||||||
import static org.samo_lego.simpleauth.utils.UuidConverter.convertUuid;
|
|
||||||
|
|
||||||
public class LogoutCommand {
|
public class LogoutCommand {
|
||||||
|
|
||||||
|
@ -22,15 +21,8 @@ public class LogoutCommand {
|
||||||
|
|
||||||
private static int logout(ServerCommandSource serverCommandSource) throws CommandSyntaxException {
|
private static int logout(ServerCommandSource serverCommandSource) throws CommandSyntaxException {
|
||||||
ServerPlayerEntity player = serverCommandSource.getPlayer();
|
ServerPlayerEntity player = serverCommandSource.getPlayer();
|
||||||
PlayerCache playerCache = playerCacheMap.get(convertUuid(player));
|
|
||||||
playerCache.lastLocation.lastDim = String.valueOf(player.getEntityWorld().getRegistryKey().getValue());
|
|
||||||
playerCache.lastLocation.lastX = player.getX();
|
|
||||||
playerCache.lastLocation.lastY = player.getY();
|
|
||||||
playerCache.lastLocation.lastZ = player.getZ();
|
|
||||||
playerCache.lastLocation.lastYaw = player.yaw;
|
|
||||||
playerCache.lastLocation.lastPitch = player.pitch;
|
|
||||||
|
|
||||||
deauthenticatePlayer(player);
|
((PlayerAuth) player).setAuthenticated(false);
|
||||||
player.sendMessage(new LiteralText(config.lang.successfulLogout), false);
|
player.sendMessage(new LiteralText(config.lang.successfulLogout), false);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.LiteralText;
|
import net.minecraft.text.LiteralText;
|
||||||
import org.samo_lego.simpleauth.storage.PlayerCache;
|
import org.samo_lego.simpleauth.storage.PlayerCache;
|
||||||
|
import org.samo_lego.simpleauth.utils.PlayerAuth;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.word;
|
import static com.mojang.brigadier.arguments.StringArgumentType.word;
|
||||||
|
@ -13,7 +14,6 @@ import static net.minecraft.server.command.CommandManager.argument;
|
||||||
import static net.minecraft.server.command.CommandManager.literal;
|
import static net.minecraft.server.command.CommandManager.literal;
|
||||||
import static org.samo_lego.simpleauth.SimpleAuth.*;
|
import static org.samo_lego.simpleauth.SimpleAuth.*;
|
||||||
import static org.samo_lego.simpleauth.utils.AuthHelper.hashPassword;
|
import static org.samo_lego.simpleauth.utils.AuthHelper.hashPassword;
|
||||||
import static org.samo_lego.simpleauth.utils.UuidConverter.convertUuid;
|
|
||||||
|
|
||||||
|
|
||||||
public class RegisterCommand {
|
public class RegisterCommand {
|
||||||
|
@ -39,7 +39,7 @@ public class RegisterCommand {
|
||||||
player.sendMessage(new LiteralText(config.lang.loginRequired), false);
|
player.sendMessage(new LiteralText(config.lang.loginRequired), false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if(isAuthenticated(player)) {
|
else if(((PlayerAuth) player).isAuthenticated()) {
|
||||||
player.sendMessage(new LiteralText(config.lang.alreadyAuthenticated), false);
|
player.sendMessage(new LiteralText(config.lang.alreadyAuthenticated), false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,11 @@ public class RegisterCommand {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerCache playerCache = playerCacheMap.get(convertUuid(player));
|
PlayerCache playerCache = playerCacheMap.get(((PlayerAuth) player).getFakeUuid());
|
||||||
if (!playerCache.isRegistered) {
|
if (!playerCache.isRegistered) {
|
||||||
authenticatePlayer(player, new LiteralText(config.lang.registerSuccess));
|
((PlayerAuth) player).setAuthenticated(true);
|
||||||
|
player.sendMessage(new LiteralText(config.lang.registerSuccess), false);
|
||||||
|
|
||||||
playerCache.password = hashPassword(pass1.toCharArray());
|
playerCache.password = hashPassword(pass1.toCharArray());
|
||||||
playerCache.isRegistered = true;
|
playerCache.isRegistered = true;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -13,13 +13,14 @@ import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.TypedActionResult;
|
import net.minecraft.util.TypedActionResult;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import org.samo_lego.simpleauth.storage.PlayerCache;
|
import org.samo_lego.simpleauth.storage.PlayerCache;
|
||||||
|
import org.samo_lego.simpleauth.utils.PlayerAuth;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static org.samo_lego.simpleauth.SimpleAuth.*;
|
import static org.samo_lego.simpleauth.SimpleAuth.config;
|
||||||
import static org.samo_lego.simpleauth.utils.UuidConverter.convertUuid;
|
import static org.samo_lego.simpleauth.SimpleAuth.playerCacheMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class will take care of actions players try to do,
|
* This class will take care of actions players try to do,
|
||||||
|
@ -40,7 +41,7 @@ public class AuthEventHandler {
|
||||||
Pattern pattern = Pattern.compile(regex);
|
Pattern pattern = Pattern.compile(regex);
|
||||||
Matcher matcher = pattern.matcher(incomingPlayerUsername);
|
Matcher matcher = pattern.matcher(incomingPlayerUsername);
|
||||||
|
|
||||||
if((onlinePlayer != null && !isPlayerFake(onlinePlayer)) && config.experimental.preventAnotherLocationKick) {
|
if((onlinePlayer != null && !((PlayerAuth) onlinePlayer).canSkipAuth()) && config.experimental.preventAnotherLocationKick) {
|
||||||
// Player needs to be kicked, since there's already a player with that name
|
// Player needs to be kicked, since there's already a player with that name
|
||||||
// playing on the server
|
// playing on the server
|
||||||
return new LiteralText(
|
return new LiteralText(
|
||||||
|
@ -63,10 +64,10 @@ public class AuthEventHandler {
|
||||||
// Player joining the server
|
// Player joining the server
|
||||||
public static void onPlayerJoin(ServerPlayerEntity player) {
|
public static void onPlayerJoin(ServerPlayerEntity player) {
|
||||||
// If player is fake auth is not needed
|
// If player is fake auth is not needed
|
||||||
if (isPlayerFake(player))
|
if (((PlayerAuth) player).canSkipAuth())
|
||||||
return;
|
return;
|
||||||
// Checking if session is still valid
|
// Checking if session is still valid
|
||||||
String uuid = convertUuid(player);
|
String uuid = ((PlayerAuth) player).getFakeUuid();
|
||||||
PlayerCache playerCache = playerCacheMap.getOrDefault(uuid, null);
|
PlayerCache playerCache = playerCacheMap.getOrDefault(uuid, null);
|
||||||
|
|
||||||
if (playerCache != null) {
|
if (playerCache != null) {
|
||||||
|
@ -75,7 +76,7 @@ public class AuthEventHandler {
|
||||||
playerCache.validUntil >= System.currentTimeMillis() &&
|
playerCache.validUntil >= System.currentTimeMillis() &&
|
||||||
player.getIp().equals(playerCache.lastIp)
|
player.getIp().equals(playerCache.lastIp)
|
||||||
) {
|
) {
|
||||||
authenticatePlayer(player, null); // Makes player authenticated
|
((PlayerAuth) player).setAuthenticated(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.setInvulnerable(config.experimental.playerInvulnerable);
|
player.setInvulnerable(config.experimental.playerInvulnerable);
|
||||||
|
@ -83,17 +84,15 @@ public class AuthEventHandler {
|
||||||
|
|
||||||
// Invalidating session
|
// Invalidating session
|
||||||
playerCache.isAuthenticated = false;
|
playerCache.isAuthenticated = false;
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
if(config.main.spawnOnJoin)
|
||||||
|
((PlayerAuth) player).hidePosition(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
deauthenticatePlayer(player);
|
((PlayerAuth) player).setAuthenticated(false);
|
||||||
playerCache = playerCacheMap.get(uuid);
|
playerCache = playerCacheMap.get(uuid);
|
||||||
playerCache.wasOnFire = false;
|
playerCache.wasOnFire = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config.main.spawnOnJoin)
|
|
||||||
teleportPlayer(player, true);
|
|
||||||
|
|
||||||
|
|
||||||
// Tries to rescue player from nether portal
|
// Tries to rescue player from nether portal
|
||||||
if(config.main.tryPortalRescue && player.getBlockState().getBlock().equals(Blocks.NETHER_PORTAL)) {
|
if(config.main.tryPortalRescue && player.getBlockState().getBlock().equals(Blocks.NETHER_PORTAL)) {
|
||||||
|
@ -112,27 +111,24 @@ public class AuthEventHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onPlayerLeave(ServerPlayerEntity player) {
|
public static void onPlayerLeave(ServerPlayerEntity player) {
|
||||||
if(isPlayerFake(player))
|
if(((PlayerAuth) player).canSkipAuth())
|
||||||
return;
|
return;
|
||||||
String uuid = convertUuid(player);
|
String uuid = ((PlayerAuth) player).getFakeUuid();
|
||||||
PlayerCache playerCache = playerCacheMap.get(uuid);
|
PlayerCache playerCache = playerCacheMap.get(uuid);
|
||||||
|
|
||||||
|
if(((PlayerAuth) player).isAuthenticated()) {
|
||||||
playerCache.lastIp = player.getIp();
|
playerCache.lastIp = player.getIp();
|
||||||
playerCache.lastAir = player.getAir();
|
playerCache.lastAir = player.getAir();
|
||||||
playerCache.wasOnFire = player.isOnFire();
|
playerCache.wasOnFire = player.isOnFire();
|
||||||
playerCache.wasInPortal = player.getBlockState().getBlock().equals(Blocks.NETHER_PORTAL);
|
playerCache.wasInPortal = player.getBlockState().getBlock().equals(Blocks.NETHER_PORTAL);
|
||||||
if(isAuthenticated(player)) {
|
|
||||||
playerCache.lastLocation.lastDim = String.valueOf(player.getEntityWorld().getRegistryKey().getValue());
|
|
||||||
playerCache.lastLocation.lastX = player.getX();
|
|
||||||
playerCache.lastLocation.lastY = player.getY();
|
|
||||||
playerCache.lastLocation.lastZ = player.getZ();
|
|
||||||
playerCache.lastLocation.lastYaw = player.yaw;
|
|
||||||
playerCache.lastLocation.lastPitch = player.pitch;
|
|
||||||
|
|
||||||
// Setting the session expire time
|
// Setting the session expire time
|
||||||
if(config.main.sessionTimeoutTime != -1)
|
if(config.main.sessionTimeoutTime != -1)
|
||||||
playerCache.validUntil = System.currentTimeMillis() + config.main.sessionTimeoutTime * 1000;
|
playerCache.validUntil = System.currentTimeMillis() + config.main.sessionTimeoutTime * 1000;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
((PlayerAuth) player).hidePosition(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player chatting
|
// Player chatting
|
||||||
|
@ -140,12 +136,12 @@ public class AuthEventHandler {
|
||||||
// Getting the message to then be able to check it
|
// Getting the message to then be able to check it
|
||||||
String msg = chatMessageC2SPacket.getChatMessage();
|
String msg = chatMessageC2SPacket.getChatMessage();
|
||||||
if(
|
if(
|
||||||
!isAuthenticated((ServerPlayerEntity) player) &&
|
!((PlayerAuth) player).isAuthenticated() &&
|
||||||
!msg.startsWith("/login") &&
|
!msg.startsWith("/login") &&
|
||||||
!msg.startsWith("/register") &&
|
!msg.startsWith("/register") &&
|
||||||
(!config.experimental.allowChat || msg.startsWith("/"))
|
(!config.experimental.allowChat || msg.startsWith("/"))
|
||||||
) {
|
) {
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
player.sendMessage(((PlayerAuth) player).getAuthMessage(), false);
|
||||||
return ActionResult.FAIL;
|
return ActionResult.FAIL;
|
||||||
}
|
}
|
||||||
return ActionResult.PASS;
|
return ActionResult.PASS;
|
||||||
|
@ -154,7 +150,7 @@ public class AuthEventHandler {
|
||||||
// Player movement
|
// Player movement
|
||||||
public static ActionResult onPlayerMove(PlayerEntity player) {
|
public static ActionResult onPlayerMove(PlayerEntity player) {
|
||||||
// Player will fall if enabled (prevent fly kick)
|
// Player will fall if enabled (prevent fly kick)
|
||||||
boolean auth = isAuthenticated((ServerPlayerEntity) player);
|
boolean auth = ((PlayerAuth) player).isAuthenticated();
|
||||||
if(!auth && config.main.allowFalling && !player.isOnGround() && !player.isInsideWaterOrBubbleColumn()) {
|
if(!auth && config.main.allowFalling && !player.isOnGround() && !player.isInsideWaterOrBubbleColumn()) {
|
||||||
if(player.isInvulnerable())
|
if(player.isInvulnerable())
|
||||||
player.setInvulnerable(false);
|
player.setInvulnerable(false);
|
||||||
|
@ -171,8 +167,8 @@ public class AuthEventHandler {
|
||||||
|
|
||||||
// Using a block (right-click function)
|
// Using a block (right-click function)
|
||||||
public static ActionResult onUseBlock(PlayerEntity player) {
|
public static ActionResult onUseBlock(PlayerEntity player) {
|
||||||
if(!isAuthenticated((ServerPlayerEntity) player) && !config.experimental.allowBlockUse) {
|
if(!((PlayerAuth) player).isAuthenticated() && !config.experimental.allowBlockUse) {
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
player.sendMessage(((PlayerAuth) player).getAuthMessage(), false);
|
||||||
return ActionResult.FAIL;
|
return ActionResult.FAIL;
|
||||||
}
|
}
|
||||||
return ActionResult.PASS;
|
return ActionResult.PASS;
|
||||||
|
@ -180,8 +176,8 @@ public class AuthEventHandler {
|
||||||
|
|
||||||
// Breaking a block
|
// Breaking a block
|
||||||
public static boolean onBreakBlock(PlayerEntity player) {
|
public static boolean onBreakBlock(PlayerEntity player) {
|
||||||
if(!isAuthenticated((ServerPlayerEntity) player) && !config.experimental.allowBlockPunch) {
|
if(!((PlayerAuth) player).isAuthenticated() && !config.experimental.allowBlockPunch) {
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
player.sendMessage(((PlayerAuth) player).getAuthMessage(), false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -189,8 +185,8 @@ public class AuthEventHandler {
|
||||||
|
|
||||||
// Using an item
|
// Using an item
|
||||||
public static TypedActionResult<ItemStack> onUseItem(PlayerEntity player) {
|
public static TypedActionResult<ItemStack> onUseItem(PlayerEntity player) {
|
||||||
if(!isAuthenticated((ServerPlayerEntity) player) && !config.experimental.allowItemUse) {
|
if(!((PlayerAuth) player).isAuthenticated() && !config.experimental.allowItemUse) {
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
player.sendMessage(((PlayerAuth) player).getAuthMessage(), false);
|
||||||
return TypedActionResult.fail(ItemStack.EMPTY);
|
return TypedActionResult.fail(ItemStack.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,16 +194,16 @@ public class AuthEventHandler {
|
||||||
}
|
}
|
||||||
// Dropping an item
|
// Dropping an item
|
||||||
public static ActionResult onDropItem(PlayerEntity player) {
|
public static ActionResult onDropItem(PlayerEntity player) {
|
||||||
if(!isAuthenticated((ServerPlayerEntity) player) && !config.experimental.allowItemDrop) {
|
if(!((PlayerAuth) player).isAuthenticated() && !config.experimental.allowItemDrop) {
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
player.sendMessage(((PlayerAuth) player).getAuthMessage(), false);
|
||||||
return ActionResult.FAIL;
|
return ActionResult.FAIL;
|
||||||
}
|
}
|
||||||
return ActionResult.PASS;
|
return ActionResult.PASS;
|
||||||
}
|
}
|
||||||
// Changing inventory (item moving etc.)
|
// Changing inventory (item moving etc.)
|
||||||
public static ActionResult onTakeItem(PlayerEntity player) {
|
public static ActionResult onTakeItem(PlayerEntity player) {
|
||||||
if(!isAuthenticated((ServerPlayerEntity) player) && !config.experimental.allowItemMoving) {
|
if(!((PlayerAuth) player).isAuthenticated() && !config.experimental.allowItemMoving) {
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
player.sendMessage(((PlayerAuth) player).getAuthMessage(), false);
|
||||||
return ActionResult.FAIL;
|
return ActionResult.FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,8 +211,8 @@ public class AuthEventHandler {
|
||||||
}
|
}
|
||||||
// Attacking an entity
|
// Attacking an entity
|
||||||
public static ActionResult onAttackEntity(PlayerEntity player) {
|
public static ActionResult onAttackEntity(PlayerEntity player) {
|
||||||
if(!isAuthenticated((ServerPlayerEntity) player) && !config.experimental.allowEntityPunch) {
|
if(!((PlayerAuth) player).isAuthenticated() && !config.experimental.allowEntityPunch) {
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
player.sendMessage(((PlayerAuth) player).getAuthMessage(), false);
|
||||||
return ActionResult.FAIL;
|
return ActionResult.FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,8 +220,8 @@ public class AuthEventHandler {
|
||||||
}
|
}
|
||||||
// Interacting with entity
|
// Interacting with entity
|
||||||
public static ActionResult onUseEntity(PlayerEntity player) {
|
public static ActionResult onUseEntity(PlayerEntity player) {
|
||||||
if(!isAuthenticated((ServerPlayerEntity) player) && !config.main.allowEntityInteract) {
|
if(!((PlayerAuth) player).isAuthenticated() && !config.main.allowEntityInteract) {
|
||||||
player.sendMessage(notAuthenticated(player), false);
|
player.sendMessage(((PlayerAuth) player).getAuthMessage(), false);
|
||||||
return ActionResult.FAIL;
|
return ActionResult.FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,216 @@
|
||||||
package org.samo_lego.simpleauth.mixin;
|
package org.samo_lego.simpleauth.mixin;
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
|
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraft.util.registry.RegistryKey;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import org.samo_lego.simpleauth.SimpleAuth;
|
||||||
import org.samo_lego.simpleauth.event.item.DropItemCallback;
|
import org.samo_lego.simpleauth.event.item.DropItemCallback;
|
||||||
|
import org.samo_lego.simpleauth.storage.PlayerCache;
|
||||||
|
import org.samo_lego.simpleauth.utils.PlayerAuth;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import static org.samo_lego.simpleauth.SimpleAuth.config;
|
||||||
|
import static org.samo_lego.simpleauth.SimpleAuth.playerCacheMap;
|
||||||
|
import static org.samo_lego.simpleauth.utils.CarpetHelper.isPlayerCarpetFake;
|
||||||
|
|
||||||
@Mixin(PlayerEntity.class)
|
@Mixin(PlayerEntity.class)
|
||||||
public abstract class MixinPlayerEntity {
|
public abstract class MixinPlayerEntity implements PlayerAuth {
|
||||||
|
|
||||||
|
private final ServerPlayerEntity player = (ServerPlayerEntity) (Object) this;
|
||||||
|
|
||||||
|
// * 20 for 20 ticks in second
|
||||||
|
private int kickTimer = config.main.kickTime * 20;
|
||||||
|
|
||||||
|
private final boolean isRunningCarpet = FabricLoader.getInstance().isModLoaded("carpet");
|
||||||
|
|
||||||
|
private final MinecraftServer server = player.getServer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Teleports player to spawn or last location that is recorded.
|
||||||
|
* Last location means the location before de-authentication.
|
||||||
|
*
|
||||||
|
* @param hide whether to teleport player to spawn (provided in config) or last recorded position
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void hidePosition(boolean hide) {
|
||||||
|
assert server != null;
|
||||||
|
|
||||||
|
PlayerCache cache = playerCacheMap.get(this.getFakeUuid());
|
||||||
|
System.out.println("Teleporting Player. hide:" + hide);
|
||||||
|
if (hide) {
|
||||||
|
// Saving position
|
||||||
|
cache.lastLocation.dimension = player.getServerWorld();
|
||||||
|
cache.lastLocation.position = player.getPos();
|
||||||
|
cache.lastLocation.yaw = player.yaw;
|
||||||
|
cache.lastLocation.pitch = player.pitch;
|
||||||
|
|
||||||
|
// Teleports player to spawn
|
||||||
|
player.teleport(
|
||||||
|
server.getWorld(RegistryKey.of(Registry.DIMENSION, new Identifier(config.worldSpawn.dimension))),
|
||||||
|
config.worldSpawn.x,
|
||||||
|
config.worldSpawn.y,
|
||||||
|
config.worldSpawn.z,
|
||||||
|
config.worldSpawn.yaw,
|
||||||
|
config.worldSpawn.pitch
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Puts player to last cached position
|
||||||
|
player.teleport(
|
||||||
|
cache.lastLocation.dimension,
|
||||||
|
cache.lastLocation.position.getX(),
|
||||||
|
cache.lastLocation.position.getY(),
|
||||||
|
cache.lastLocation.position.getZ(),
|
||||||
|
cache.lastLocation.yaw,
|
||||||
|
cache.lastLocation.pitch
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts player uuid, to ensure player with "nAmE" and "NamE" get same uuid.
|
||||||
|
* Both players are not allowed to play, since mod mimics Mojang behaviour.
|
||||||
|
* of not allowing accounts with same names but different capitalization.
|
||||||
|
*
|
||||||
|
* @return converted UUID as string
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getFakeUuid() {
|
||||||
|
// If server is in online mode online-mode UUIDs should be used
|
||||||
|
assert server != null;
|
||||||
|
if(server.isOnlineMode())
|
||||||
|
return player.getUuidAsString();
|
||||||
|
/*
|
||||||
|
Lower case is used for Player and PlAyEr to get same UUID (for password storing)
|
||||||
|
Mimicking Mojang behaviour, where players cannot set their name to
|
||||||
|
ExAmple if Example is already taken.
|
||||||
|
*/
|
||||||
|
String playername = player.getName().asString().toLowerCase();
|
||||||
|
return PlayerEntity.getOfflinePlayerUuid(playername).toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the authentication status of the player.
|
||||||
|
*
|
||||||
|
* @param authenticated whether player should be authenticated
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setAuthenticated(boolean authenticated) {
|
||||||
|
PlayerCache playerCache;
|
||||||
|
|
||||||
|
if(!playerCacheMap.containsKey(this.getFakeUuid())) {
|
||||||
|
// First join
|
||||||
|
playerCache = new PlayerCache(this.getFakeUuid(), player);
|
||||||
|
playerCacheMap.put(this.getFakeUuid(), playerCache);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
playerCache = playerCacheMap.get(this.getFakeUuid());
|
||||||
|
if(this.isAuthenticated() == authenticated)
|
||||||
|
return;
|
||||||
|
playerCache.isAuthenticated = authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.setInvulnerable(!authenticated && config.experimental.playerInvulnerable);
|
||||||
|
player.setInvisible(!authenticated && config.experimental.playerInvisible);
|
||||||
|
|
||||||
|
// Teleporting player (hiding / restoring position)
|
||||||
|
if(config.main.spawnOnJoin)
|
||||||
|
this.hidePosition(!authenticated);
|
||||||
|
|
||||||
|
if(authenticated) {
|
||||||
|
kickTimer = config.main.kickTime * 20;
|
||||||
|
// Updating blocks if needed (if portal rescue action happened)
|
||||||
|
if(playerCache.wasInPortal) {
|
||||||
|
World world = player.getEntityWorld();
|
||||||
|
BlockPos pos = player.getBlockPos();
|
||||||
|
|
||||||
|
// Sending updates to portal blocks
|
||||||
|
// This is technically not needed, but it cleans the "messed portal" on the client
|
||||||
|
world.updateListeners(pos, world.getBlockState(pos), world.getBlockState(pos), 3);
|
||||||
|
world.updateListeners(pos.up(), world.getBlockState(pos.up()), world.getBlockState(pos.up()), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setting last air to player
|
||||||
|
if(player.isSubmergedInWater())
|
||||||
|
player.setAir(playerCache.lastAir);
|
||||||
|
|
||||||
|
// In case player is in lava during authentication proccess
|
||||||
|
if(!playerCache.wasOnFire)
|
||||||
|
player.setFireTicks(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the text which tells the player
|
||||||
|
* to login or register, depending on account status.
|
||||||
|
*
|
||||||
|
* @return LiteralText with appropriate string (login or register)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Text getAuthMessage() {
|
||||||
|
final PlayerCache cache = playerCacheMap.get(((PlayerAuth) player).getFakeUuid());
|
||||||
|
if(SimpleAuth.config.main.enableGlobalPassword || cache.isRegistered)
|
||||||
|
return new LiteralText(
|
||||||
|
SimpleAuth.config.lang.notAuthenticated + "\n" + SimpleAuth.config.lang.loginRequired
|
||||||
|
);
|
||||||
|
return new LiteralText(
|
||||||
|
SimpleAuth.config.lang.notAuthenticated+ "\n" + SimpleAuth.config.lang.registerRequired
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether player is a fake player (from CarpetMod).
|
||||||
|
*
|
||||||
|
* @return true if player is fake (can skip authentication process), otherwise false
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canSkipAuth() {
|
||||||
|
// We ask CarpetHelper class since it has the imports needed
|
||||||
|
return this.isRunningCarpet && isPlayerCarpetFake(this.player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether player is authenticated.
|
||||||
|
*
|
||||||
|
* @return false if player is not authenticated, otherwise true.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isAuthenticated() {
|
||||||
|
String uuid = ((PlayerAuth) player).getFakeUuid();
|
||||||
|
return playerCacheMap.containsKey(uuid) && playerCacheMap.get(uuid).isAuthenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "tick()V", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void tick(CallbackInfo ci) {
|
||||||
|
if(!this.isAuthenticated()) {
|
||||||
|
// Checking player timer
|
||||||
|
if(kickTimer <= 0 && player.networkHandler.getConnection().isOpen()) {
|
||||||
|
player.networkHandler.disconnect(new LiteralText(config.lang.timeExpired));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Sending authentication prompt every 10 seconds
|
||||||
|
if(kickTimer % 200 == 0)
|
||||||
|
player.sendMessage(this.getAuthMessage(), false);
|
||||||
|
kickTimer--;
|
||||||
|
}
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Player item dropping
|
// Player item dropping
|
||||||
@Inject(method = "dropSelectedItem(Z)Z", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "dropSelectedItem(Z)Z", at = @At("HEAD"), cancellable = true)
|
||||||
private void dropSelectedItem(boolean dropEntireStack, CallbackInfoReturnable<Boolean> cir) {
|
private void dropSelectedItem(boolean dropEntireStack, CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ public abstract class MixinPlayerManager {
|
||||||
PlayerJoinServerCallback.EVENT.invoker().onPlayerJoin(serverPlayerEntity);
|
PlayerJoinServerCallback.EVENT.invoker().onPlayerJoin(serverPlayerEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "remove(Lnet/minecraft/server/network/ServerPlayerEntity;)V", at = @At("RETURN"))
|
@Inject(method = "remove(Lnet/minecraft/server/network/ServerPlayerEntity;)V", at = @At("HEAD"))
|
||||||
private void onPlayerLeave(ServerPlayerEntity serverPlayerEntity, CallbackInfo ci) {
|
private void onPlayerLeave(ServerPlayerEntity serverPlayerEntity, CallbackInfo ci) {
|
||||||
PlayerLeaveServerCallback.EVENT.invoker().onPlayerLeave(serverPlayerEntity);
|
PlayerLeaveServerCallback.EVENT.invoker().onPlayerLeave(serverPlayerEntity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,12 +86,12 @@ public class AuthConfig {
|
||||||
public boolean allowFalling = false;
|
public boolean allowFalling = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to tp player to spawn when joining (to hide coordinates).
|
* Whether to tp player to spawn when joining (to hide original player coordinates).
|
||||||
*/
|
*/
|
||||||
public boolean spawnOnJoin = false;
|
public boolean spawnOnJoin = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data for spawn (where deauthenticated players are teleported).
|
* Data for spawn (where deauthenticated players are teleported temporarily).
|
||||||
* @see <a href="https://github.com/samolego/SimpleAuth/wiki/Coordinate-Hiding" target="_blank">wiki</a>
|
* @see <a href="https://github.com/samolego/SimpleAuth/wiki/Coordinate-Hiding" target="_blank">wiki</a>
|
||||||
*/
|
*/
|
||||||
public static class WorldSpawn {
|
public static class WorldSpawn {
|
||||||
|
|
|
@ -4,6 +4,14 @@ import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraft.util.registry.RegistryKey;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -52,12 +60,10 @@ public class PlayerCache {
|
||||||
* Last recorded position before de-authentication.
|
* Last recorded position before de-authentication.
|
||||||
*/
|
*/
|
||||||
public static class LastLocation {
|
public static class LastLocation {
|
||||||
public String lastDim;
|
public ServerWorld dimension;
|
||||||
public double lastX;
|
public Vec3d position;
|
||||||
public double lastY;
|
public float yaw;
|
||||||
public double lastZ;
|
public float pitch;
|
||||||
public float lastYaw;
|
|
||||||
public float lastPitch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerCache.LastLocation lastLocation = new PlayerCache.LastLocation();
|
public PlayerCache.LastLocation lastLocation = new PlayerCache.LastLocation();
|
||||||
|
@ -79,13 +85,12 @@ public class PlayerCache {
|
||||||
this.lastAir = player.getAir();
|
this.lastAir = player.getAir();
|
||||||
|
|
||||||
// Setting position cache
|
// Setting position cache
|
||||||
this.lastLocation.lastDim = String.valueOf(player.getEntityWorld().getRegistryKey().getValue());
|
this.lastLocation.dimension = player.getServerWorld();
|
||||||
|
this.lastLocation.position = player.getPos();
|
||||||
|
this.lastLocation.yaw = player.yaw;
|
||||||
|
this.lastLocation.pitch = player.pitch;
|
||||||
|
|
||||||
this.wasInPortal = player.getBlockState().getBlock().equals(Blocks.NETHER_PORTAL);
|
this.wasInPortal = player.getBlockState().getBlock().equals(Blocks.NETHER_PORTAL);
|
||||||
this.lastLocation.lastX = player.getX();
|
|
||||||
this.lastLocation.lastY = player.getY();
|
|
||||||
this.lastLocation.lastZ = player.getZ();
|
|
||||||
this.lastLocation.lastYaw = player.yaw;
|
|
||||||
this.lastLocation.lastPitch = player.pitch;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.wasOnFire = false;
|
this.wasOnFire = false;
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package org.samo_lego.simpleauth.utils;
|
||||||
|
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PLayer authentication extension.
|
||||||
|
*/
|
||||||
|
public interface PlayerAuth {
|
||||||
|
/**
|
||||||
|
* Teleports player to spawn or last location that is recorded.
|
||||||
|
* Last location means the location before de-authentication.
|
||||||
|
*
|
||||||
|
* @param hide whether to teleport player to spawn (provided in config) or last recorded position
|
||||||
|
* @see <a href="https://samolego.github.io/SimpleAuth/org/samo_lego/simpleauth/mixin/MixinPlayerEntity.html">See implementation</a>
|
||||||
|
*/
|
||||||
|
void hidePosition(boolean hide);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts player uuid, to ensure player with "nAmE" and "NamE" get same uuid.
|
||||||
|
* Both players are not allowed to play, since mod mimics Mojang behaviour.
|
||||||
|
* of not allowing accounts with same names but different capitalization.
|
||||||
|
*
|
||||||
|
* @return converted UUID as string
|
||||||
|
* @see <a href="https://samolego.github.io/SimpleAuth/org/samo_lego/simpleauth/mixin/MixinPlayerEntity.html">See implementation</a>
|
||||||
|
*/
|
||||||
|
String getFakeUuid();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the authentication status of the player.
|
||||||
|
*
|
||||||
|
* @param authenticated whether player should be authenticated
|
||||||
|
* @see <a href="https://samolego.github.io/SimpleAuth/org/samo_lego/simpleauth/mixin/MixinPlayerEntity.html">See implementation</a>
|
||||||
|
*/
|
||||||
|
void setAuthenticated(boolean authenticated);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether player is authenticated.
|
||||||
|
*
|
||||||
|
* @return false if player is not authenticated, otherwise true.
|
||||||
|
* @see <a href="https://samolego.github.io/SimpleAuth/org/samo_lego/simpleauth/mixin/MixinPlayerEntity.html">See implementation</a>
|
||||||
|
*/
|
||||||
|
boolean isAuthenticated();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the text which tells the player
|
||||||
|
* to login or register, depending on account status.
|
||||||
|
*
|
||||||
|
* @return LiteralText with appropriate string (login or register)
|
||||||
|
* @see <a href="https://samolego.github.io/SimpleAuth/org/samo_lego/simpleauth/mixin/MixinPlayerEntity.html">See implementation</a>
|
||||||
|
*/
|
||||||
|
Text getAuthMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether player is a fake player (from CarpetMod).
|
||||||
|
*
|
||||||
|
* @return true if player is fake (can skip authentication process), otherwise false
|
||||||
|
* @see <a href="https://samolego.github.io/SimpleAuth/org/samo_lego/simpleauth/mixin/MixinPlayerEntity.html">See implementation</a>
|
||||||
|
*/
|
||||||
|
boolean canSkipAuth();
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
package org.samo_lego.simpleauth.utils;
|
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
|
|
||||||
import static org.samo_lego.simpleauth.SimpleAuth.serverProp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts player uuid, to ensure player with "nAmE" and "NamE" get same uuid
|
|
||||||
* Both players are not allowed to play, since mod mimics Mojang behaviour
|
|
||||||
* of not allowing accounts with same names but different capitalization
|
|
||||||
*/
|
|
||||||
public class UuidConverter {
|
|
||||||
|
|
||||||
private static final boolean isOnline = Boolean.parseBoolean(serverProp.getProperty("online-mode"));
|
|
||||||
|
|
||||||
/** Gets player UUID.
|
|
||||||
*
|
|
||||||
* @param player player to get UUID for
|
|
||||||
* @return converted UUID as string
|
|
||||||
*/
|
|
||||||
public static String convertUuid(PlayerEntity player) {
|
|
||||||
// If server is in online mode online-mode UUIDs should be used
|
|
||||||
if(isOnline)
|
|
||||||
return player.getUuidAsString();
|
|
||||||
/*
|
|
||||||
Lower case is used for Player and PlAyEr to get same UUID (for password storing)
|
|
||||||
Mimicking Mojang behaviour, where players cannot set their name to
|
|
||||||
ExAmple if Example is already taken.
|
|
||||||
*/
|
|
||||||
String playername = player.getName().asString().toLowerCase();
|
|
||||||
return PlayerEntity.getOfflinePlayerUuid(playername).toString();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue