Moved to Fabric API events

As well as fixed some bugs and did some changes to /auth
This commit is contained in:
samo_lego 2019-11-17 20:07:54 +01:00
parent c51fdc7c0a
commit 8054a8fa6d
13 changed files with 126 additions and 187 deletions

View File

@ -1,8 +1,9 @@
package org.samo_lego.simpleauth;
import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.event.player.*;
import net.fabricmc.fabric.api.registry.CommandRegistry;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -12,12 +13,9 @@ import org.samo_lego.simpleauth.commands.LoginCommand;
import org.samo_lego.simpleauth.commands.RegisterCommand;
import org.samo_lego.simpleauth.database.SimpleAuthDatabase;
import org.samo_lego.simpleauth.event.AuthEventHandler;
import org.samo_lego.simpleauth.event.block.BreakBlockCallback;
import org.samo_lego.simpleauth.event.block.InteractBlockCallback;
import org.samo_lego.simpleauth.event.item.DropItemCallback;
import org.samo_lego.simpleauth.event.item.InteractItemCallback;
import org.samo_lego.simpleauth.event.entity.player.PlayerJoinServerCallback;
import org.samo_lego.simpleauth.event.entity.player.PlayerLeaveServerCallback;
import org.samo_lego.simpleauth.event.item.DropItemCallback;
import java.io.File;
import java.util.HashSet;
@ -48,18 +46,20 @@ public class SimpleAuth implements DedicatedServerModInitializer {
});
// Registering the events
InteractBlockCallback.EVENT.register(AuthEventHandler::onInteractBlock);
BreakBlockCallback.EVENT.register((world, pos, state, player) -> AuthEventHandler.onBlockBroken(player));
InteractItemCallback.EVENT.register(AuthEventHandler::onInteractItem);
DropItemCallback.EVENT.register(AuthEventHandler::onDropItem);
PlayerJoinServerCallback.EVENT.register(AuthEventHandler::onPlayerJoin);
PlayerLeaveServerCallback.EVENT.register(AuthEventHandler::onPlayerLeave);
DropItemCallback.EVENT.register(player -> AuthEventHandler.onDropItem(player));
// From Fabric API
AttackBlockCallback.EVENT.register((playerEntity, world, hand, blockPos, direction) -> AuthEventHandler.onAttackBlock(playerEntity));
UseBlockCallback.EVENT.register((player, world, hand, blockHitResult) -> AuthEventHandler.onUseBlock(player));
UseItemCallback.EVENT.register((player, world, hand) -> AuthEventHandler.onUseItem(player));
AttackEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> AuthEventHandler.onAttackEntity(player));
UseEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> AuthEventHandler.onUseEntity(player));
// Making a table in database
db.makeTable();
}
public static HashSet<ServerPlayerEntity> authenticatedUsers = new HashSet<>();
public static HashSet<PlayerEntity> authenticatedUsers = new HashSet<>();
public static boolean isAuthenticated(ServerPlayerEntity player) { return authenticatedUsers.contains(player); }

View File

@ -5,6 +5,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import de.mkammerer.argon2.Argon2;
import de.mkammerer.argon2.Argon2Factory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
@ -17,6 +18,8 @@ import org.samo_lego.simpleauth.SimpleAuth;
import static com.mojang.brigadier.arguments.StringArgumentType.*;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
import static org.samo_lego.simpleauth.SimpleAuth.authenticatedUsers;
import static org.samo_lego.simpleauth.SimpleAuth.isAuthenticated;
public class AuthCommand {
private static final Logger LOGGER = LogManager.getLogger();
@ -29,43 +32,68 @@ public class AuthCommand {
dispatcher.register(literal("auth")
.requires(source -> source.hasPermissionLevel(4))
.then(literal("update")
.then(literal("byUuid")
.then(argument("uuid", word())
.then(argument("password", word())
.executes( ctx -> updatePass(
ctx.getSource(),
getString(ctx, "uuid"),
null,
getString(ctx, "password")
))
)
)
)
.then(literal("byUsername")
.then(argument("username", word())
.then(argument("password", word())
.executes( ctx -> updatePass(
ctx.getSource(),
null,
getString(ctx, "username"),
getString(ctx, "password")
))
)
)
)
)
.then(literal("remove")
.then(literal("byUuid")
.then(argument("uuid", word())
.executes( ctx -> removeAccount(
ctx.getSource(),
getString(ctx, "uuid")
getString(ctx, "uuid"),
null
))
)
)
.then(literal("byUsername")
.then(argument("username", word())
.executes( ctx -> removeAccount(
ctx.getSource(),
null,
getString(ctx, "username")
))
)
)
)
);
}
// Method called for checking the password
private static int updatePass(ServerCommandSource source, String uuid, String pass) {
private static int updatePass(ServerCommandSource source, String uuid, String username, String pass) {
// Getting the player who send the command
Entity sender = source.getEntity();
if(uuid == null)
return -1;
// Create instance
Argon2 argon2 = Argon2Factory.create();
char[] password = pass.toCharArray();
try {
// Hashed password from DB
String hashed = SimpleAuth.db.getPassword(uuid);
String hash = argon2.hash(10, 65536, 1, pass.toCharArray());
// Writing into DB
SimpleAuth.db.update(uuid, hashed);
SimpleAuth.db.update(uuid, username, hash);
if(sender != null)
sender.sendMessage(userdataUpdated);
else
@ -74,13 +102,15 @@ public class AuthCommand {
// Wipe confidential data
argon2.wipeArray(password);
}
// TODO -> Kick player whose name was changed?
return 1; // Success
}
private static int removeAccount(ServerCommandSource source, String uuid) {
// Getting the player who send the command
private static int removeAccount(ServerCommandSource source, String uuid, String username) {
Entity sender = source.getEntity();
SimpleAuth.db.delete(uuid);
SimpleAuth.db.delete(uuid, username);
// TODO -> Kick player that was unregistered?
if(sender != null)
sender.sendMessage(userdataDeleted);
else

View File

@ -62,7 +62,7 @@ public class ChangepwCommand {
if (argon2.verify(hashedOld, password)) {
String hash = argon2.hash(10, 65536, 1, newPass.toCharArray());
// Writing into DB
SimpleAuth.db.update(player.getUuidAsString(), hash);
SimpleAuth.db.update(player.getUuidAsString(), null, hash);
player.sendMessage(passwordUpdated);
}
else

View File

@ -4,6 +4,7 @@ import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import de.mkammerer.argon2.Argon2;
import de.mkammerer.argon2.Argon2Factory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;

View File

@ -48,19 +48,22 @@ public class SimpleAuthDatabase {
// When player registers, we insert the data into DB
public boolean registerUser(String uuid, String username, String password) {
String sql = "INSERT INTO users(uuid, username, password) VALUES(?,?,?)";
String sqlCheck = "SELECT UUID, Password "
String sqlCheck = "SELECT UUID "
+ "FROM users WHERE UUID = ?";
try (
Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql);
PreparedStatement pstmtCheck = conn.prepareStatement(sql)) {
PreparedStatement pstmtCheck = conn.prepareStatement(sqlCheck)) {
pstmtCheck.setString(1,uuid);
pstmtCheck.setString(1, uuid);
ResultSet rs = pstmtCheck.executeQuery();
// Getting the password
String dbUuid = rs.getString("UUID");
if(dbUuid != null) {
//String dbUuid = null;
try {
rs.getString("UUID");
return false;
} catch(SQLException ignored) {
pstmt.setString(1, uuid);
pstmt.setString(2, username);
pstmt.setString(3, password);
@ -69,20 +72,21 @@ public class SimpleAuthDatabase {
return true;
}
} catch (SQLException e) {
LOGGER.error(e.getMessage());
}
LOGGER.error("Register error: " + e.getMessage());
return false;
}
}
// Deletes row containing the username provided
public void delete(String uuid) {
String sql = "DELETE FROM users WHERE uuid = ?";
public void delete(String uuid, String username) {
String sql = "DELETE FROM users WHERE uuid = ? OR username = ?";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// set the corresponding param
pstmt.setString(1, uuid);
pstmt.setString(2, username);
// execute the delete statement
pstmt.executeUpdate();
@ -92,9 +96,9 @@ public class SimpleAuthDatabase {
}
// Updates the password of the user
public void update(String uuid, String pass) {
public void update(String uuid, String username, String pass) {
String sql = "UPDATE users SET password = ? "
+ "WHERE uuid = ?";
+ "WHERE uuid = ? OR username = ?";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
@ -102,6 +106,7 @@ public class SimpleAuthDatabase {
// set the corresponding param
pstmt.setString(1, pass);
pstmt.setString(2, uuid);
pstmt.setString(3, username);
// update
pstmt.executeUpdate();

View File

@ -1,9 +1,7 @@
package org.samo_lego.simpleauth.event;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.ActionResult;
import org.samo_lego.simpleauth.SimpleAuth;
@ -36,8 +34,8 @@ public class AuthEventHandler {
return false;
}
// Interacting with block
public static ActionResult onInteractBlock(ServerPlayerEntity player) {
// Using a block (right-click function)
public static ActionResult onUseBlock(PlayerEntity player) {
if(!SimpleAuth.authenticatedUsers.contains(player)) {
player.sendMessage(notAuthenticated);
return ActionResult.FAIL;
@ -46,16 +44,34 @@ public class AuthEventHandler {
}
// Punching a block
public static ActionResult onAttackBlock(PlayerEntity playerEntity) {
if(!SimpleAuth.authenticatedUsers.contains(playerEntity)) {
playerEntity.sendMessage(notAuthenticated);
public static ActionResult onAttackBlock(PlayerEntity player) {
if(!SimpleAuth.authenticatedUsers.contains(player)) {
player.sendMessage(notAuthenticated);
return ActionResult.FAIL;
}
return ActionResult.PASS;
}
// Interacting with item
public static ActionResult onInteractItem(ServerPlayerEntity player) {
// Using an item
public static ActionResult onUseItem(PlayerEntity player) {
if(!SimpleAuth.authenticatedUsers.contains(player)) {
player.sendMessage(notAuthenticated);
return ActionResult.FAIL;
}
return ActionResult.PASS;
}
// Attacking an entity
public static ActionResult onAttackEntity(PlayerEntity player) {
if(!SimpleAuth.authenticatedUsers.contains(player)) {
player.sendMessage(notAuthenticated);
return ActionResult.FAIL;
}
return ActionResult.PASS;
}
// Interacting with entity
public static ActionResult onUseEntity(PlayerEntity player) {
if(!SimpleAuth.authenticatedUsers.contains(player)) {
player.sendMessage(notAuthenticated);
return ActionResult.FAIL;
@ -64,11 +80,11 @@ public class AuthEventHandler {
return ActionResult.PASS;
}
// Dropping an item
public static boolean onDropItem(ServerPlayerEntity player) {
public static ActionResult onDropItem(PlayerEntity player) {
if(!SimpleAuth.authenticatedUsers.contains(player)) {
player.sendMessage(notAuthenticated);
return true;
return ActionResult.FAIL;
}
return false;
return ActionResult.PASS;
}
}

View File

@ -1,21 +0,0 @@
package org.samo_lego.simpleauth.event.block;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public interface BreakBlockCallback {
Event<BreakBlockCallback> EVENT = EventFactory.createArrayBacked(BreakBlockCallback.class, listeners -> (world, pos, state, player) -> {
for(BreakBlockCallback callback : listeners) {
if(callback.onBlockBroken(world, pos, state, player)) {
return true;
}
}
return false;
});
boolean onBlockBroken(World world, BlockPos pos, BlockState state, PlayerEntity player);
}

View File

@ -1,20 +0,0 @@
package org.samo_lego.simpleauth.event.block;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
public interface InteractBlockCallback {
Event<InteractBlockCallback> EVENT = EventFactory.createArrayBacked(InteractBlockCallback.class,
(listeners) -> (player) -> {
for (InteractBlockCallback event : listeners) {
ActionResult result = event.onInteractBlock(player);
if(result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
});
ActionResult onInteractBlock(ServerPlayerEntity player);
}

View File

@ -2,17 +2,20 @@ package org.samo_lego.simpleauth.event.item;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
public interface DropItemCallback {
Event<DropItemCallback> EVENT = EventFactory.createArrayBacked(DropItemCallback.class, listeners -> (playerEntity) -> {
for(DropItemCallback callback : listeners) {
if(callback.onDropItem(playerEntity)) {
return true;
Event<DropItemCallback> EVENT = EventFactory.createArrayBacked(DropItemCallback.class, listeners -> (player) -> {
for (DropItemCallback event : listeners) {
ActionResult result = event.onDropItem(player);
if (result != ActionResult.PASS) {
return result;
}
}
return false;
return ActionResult.PASS;
});
boolean onDropItem(ServerPlayerEntity playerEntity);
ActionResult onDropItem(PlayerEntity player);
}

View File

@ -1,20 +0,0 @@
package org.samo_lego.simpleauth.event.item;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
public interface InteractItemCallback {
Event<InteractItemCallback> EVENT = EventFactory.createArrayBacked(InteractItemCallback.class,
(listeners) -> (player) -> {
for (InteractItemCallback event : listeners) {
ActionResult result = event.onInteractItem(player);
if(result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
});
ActionResult onInteractItem(ServerPlayerEntity player);
}

View File

@ -3,6 +3,7 @@ package org.samo_lego.simpleauth.mixin;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import org.samo_lego.simpleauth.event.item.DropItemCallback;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -12,13 +13,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PlayerEntity.class)
public abstract class MixinPlayerEntity {
// Thanks to AbusedLib https://github.com/abused/AbusedLib
@Inject(method = "dropItem(Lnet/minecraft/item/ItemStack;ZZ)Lnet/minecraft/entity/ItemEntity;", at = @At("HEAD"))
// Thanks to PR https://github.com/FabricMC/fabric/pull/260 and AbusedLib
/*@Inject(method = "dropItem(Lnet/minecraft/item/ItemStack;ZZ)Lnet/minecraft/entity/ItemEntity;", at = @At("HEAD"))
private void dropItem(ItemStack stack, boolean boolean_1, boolean boolean_2, CallbackInfoReturnable<ItemStack> info) {
ServerPlayerEntity player = (ServerPlayerEntity) (Object) this;
if(DropItemCallback.EVENT.invoker().onDropItem(player)) {
player.giveItemStack(stack);
info.setReturnValue(ItemStack.EMPTY);
}
ActionResult result = DropItemCallback.EVENT.invoker().onDropItem(player);
if (result == ActionResult.FAIL) {
info.cancel();
}
}*/
}

View File

@ -1,57 +0,0 @@
package org.samo_lego.simpleauth.mixin;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.samo_lego.simpleauth.event.block.BreakBlockCallback;
import org.samo_lego.simpleauth.event.block.InteractBlockCallback;
import org.samo_lego.simpleauth.event.item.InteractItemCallback;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ServerPlayerInteractionManager.class)
public abstract class MixinServerPlayerInteractionManager {
@Shadow public ServerWorld world;
@Shadow public ServerPlayerEntity player;
// We inject the following code to tryBreakBlock method, by TextileLib
@Inject(method = "tryBreakBlock", at = @At("HEAD"), cancellable = true)
private void tryBreakBlock(BlockPos pos, CallbackInfoReturnable<Boolean> info) {
// Triggering the event
if(BreakBlockCallback.EVENT.invoker().onBlockBroken(world, pos, world.getBlockState(pos), player)) {
info.setReturnValue(false);
}
}
// Interacting with blocks
@Inject(method="interactBlock", at = @At("HEAD"), cancellable = true)
private void interactBlock(PlayerEntity playerEntity_1, World world_1, ItemStack itemStack_1, Hand hand_1, BlockHitResult blockHitResult_1, CallbackInfoReturnable<ActionResult> info){
// Callback
ActionResult result = InteractBlockCallback.EVENT.invoker().onInteractBlock((ServerPlayerEntity) playerEntity_1);
if(result == ActionResult.FAIL) {
info.cancel();
}
}
// Interacting with items
@Inject(method="interactItem", at = @At("HEAD"), cancellable = true)
private void interactItem(PlayerEntity playerEntity_1, World world_1, ItemStack itemStack_1, Hand hand_1, CallbackInfoReturnable<ActionResult> info){
// Callback
ActionResult result = InteractItemCallback.EVENT.invoker().onInteractItem((ServerPlayerEntity) playerEntity_1);
if(result == ActionResult.FAIL) {
info.cancel();
}
}
}

View File

@ -5,7 +5,7 @@
"mixins": [
],
"server": [
"MixinServerPlayerInteractionManager",
"MixinPlayerManager",
"MixinPlayerEntity"
],