Skip to content

Commit

Permalink
Merge pull request #51 from architects-land/fix/kicking-bugs
Browse files Browse the repository at this point in the history
[Fix] Kicking can provoke bugs
  • Loading branch information
anhgelus authored Jan 19, 2025
2 parents 96203cb + 466ca01 commit 4773ff8
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package world.anhgelus.architectsland.difficultydeathscaler;

import com.mojang.authlib.GameProfile;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
Expand All @@ -22,6 +23,7 @@
import world.anhgelus.architectsland.difficultydeathscaler.difficulty.global.GlobalDifficultyManager;
import world.anhgelus.architectsland.difficultydeathscaler.difficulty.player.Bounty;
import world.anhgelus.architectsland.difficultydeathscaler.difficulty.player.PlayerDifficultyManager;
import world.anhgelus.architectsland.difficultydeathscaler.utils.Getters;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -33,17 +35,17 @@ public class DifficultyDeathScaler implements ModInitializer {
private GlobalDifficultyManager difficultyManager;

public static final GameRules.Key<GameRules.BooleanRule> ENABLE_TEMP_BAN = GameRuleRegistry.register(
MOD_ID +":enableTempBan",
MOD_ID + ":enableTempBan",
GameRules.Category.MISC,
GameRuleFactory.createBooleanRule(true)
);
public static final GameRules.Key<GameRules.IntRule> DEATH_BEFORE_TEMP_BAN = GameRuleRegistry.register(
MOD_ID +":deathBeforeTempBan",
MOD_ID + ":deathBeforeTempBan",
GameRules.Category.MISC,
GameRuleFactory.createIntRule(5)
);
public static final GameRules.Key<GameRules.IntRule> TEMP_BAN_DURATION = GameRuleRegistry.register(
MOD_ID +":tempBanDuration",
MOD_ID + ":tempBanDuration",
GameRules.Category.MISC,
GameRuleFactory.createIntRule(12)
);
Expand All @@ -56,21 +58,22 @@ public void onInitialize() {
LOGGER.info("Difficulty Death Scaler started");

CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
DifficultyCommand.setPlayerDifficultyGetter(this::getPlayerDifficultyManager);
DifficultyCommand.register(dispatcher, () -> difficultyManager);
Getters.PLAYER_DIFFICULTY_GETTER = this::getPlayerDifficultyManager;
Getters.GLOBAL_DIFFICULTY_GETTER = () -> difficultyManager;
DifficultyCommand.register(dispatcher);
});

// set up base difficulty
// set up base difficulty and player difficulty fetcher
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
difficultyManager = new GlobalDifficultyManager(server);
loadAllPlayerManagers(server);

Getters.PROFILE_DIFFICULTY_GETTER = (profile) -> getPlayerDifficultyManager(server, profile);
});

ServerLifecycleEvents.SERVER_STOPPING.register(server -> {
difficultyManager.save();
playerDifficultyManagerMap.forEach((player, manager) -> {
manager.save();
});
playerDifficultyManagerMap.forEach((player, manager) -> manager.save());
});

ServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> {
Expand Down Expand Up @@ -100,7 +103,6 @@ public void onInitialize() {

ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
final var playerDifficulty = getPlayerDifficultyManager(server, handler.player);
if (playerDifficulty.kickIfDiedTooMuch()) return;
playerDifficulty.applyModifiers();

difficultyManager.applyModifiers(handler.player);
Expand All @@ -115,22 +117,39 @@ public void onInitialize() {
bounty.onDisconnect();
});

UseEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> BossManager.handleBuff(player, world, hand, entity));
UseEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> {
return BossManager.handleBuff(player, world, hand, entity);
});

ServerEntityEvents.ENTITY_LOAD.register((entity, world) -> {
if (!(entity instanceof HostileEntity)) return;
difficultyManager.onEntitySpawn((HostileEntity) entity);
});
}

/**
* Set player in difficulty manager
*/
private PlayerDifficultyManager getPlayerDifficultyManager(MinecraftServer server, ServerPlayerEntity player) {
if (playerDifficultyManagerMap.containsKey(player.getUuid())) {
final var playerDifficulty = playerDifficultyManagerMap.get(player.getUuid());
playerDifficulty.player = player;
return playerDifficulty;
final var difficulty = getPlayerDifficultyManager(server, player.getGameProfile());
difficulty.player = player;
return difficulty;
}

/**
* Does not set player in difficulty manager!
*/
private PlayerDifficultyManager getPlayerDifficultyManager(MinecraftServer server, GameProfile profile) {
if (playerDifficultyManagerMap.containsKey(profile.getId())) {
return playerDifficultyManagerMap.get(profile.getId());
}
final var playerDifficulty = new PlayerDifficultyManager(server, difficultyManager, player);
playerDifficultyManagerMap.put(player.getUuid(), playerDifficulty);
final var playerDifficulty = new PlayerDifficultyManager(
server,
difficultyManager,
profile.getId(),
StateSaver.getPlayerState(server, profile.getId())
);
playerDifficultyManagerMap.put(profile.getId(), playerDifficulty);
return playerDifficulty;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,24 @@
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.command.argument.EntityArgumentType;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.ClickEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import world.anhgelus.architectsland.difficultydeathscaler.difficulty.global.GlobalDifficultyManager;
import world.anhgelus.architectsland.difficultydeathscaler.difficulty.player.PlayerDifficultyManager;

import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
import static world.anhgelus.architectsland.difficultydeathscaler.utils.Getters.GLOBAL_DIFFICULTY_GETTER;
import static world.anhgelus.architectsland.difficultydeathscaler.utils.Getters.PLAYER_DIFFICULTY_GETTER;

public class DifficultyCommand {

/**
* Functional interface giving the player difficulty manager
*/
@FunctionalInterface
public interface PlayerDifficultyGetter {
PlayerDifficultyManager get(MinecraftServer server, ServerPlayerEntity player);
}

/**
* Functional interface giving the global difficulty manager
*/
@FunctionalInterface
public interface GlobalDifficultyGetter {
GlobalDifficultyManager get();
}

private static PlayerDifficultyGetter playerDifficultyGetter;

public static void setPlayerDifficultyGetter(PlayerDifficultyGetter playerDifficultyGetter) {
DifficultyCommand.playerDifficultyGetter = playerDifficultyGetter;
}

public static void register(CommandDispatcher<ServerCommandSource> dispatcher, GlobalDifficultyGetter globalDifficultyGetter) {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
final Command<ServerCommandSource> globalGetExecute = context -> {
final var source = context.getSource();
final var server = source.getServer();
source.sendFeedback(() -> {
return Text.literal(globalDifficultyGetter.get().getDifficultyUpdate(server.getOverworld().getDifficulty()));
return Text.literal(GLOBAL_DIFFICULTY_GETTER.get().getDifficultyUpdate(server.getOverworld().getDifficulty()));
}, false);
return Command.SINGLE_SUCCESS;
};
Expand All @@ -63,40 +39,40 @@ public static void register(CommandDispatcher<ServerCommandSource> dispatcher, G
final var setGlobalCommand = literal("global").then(
argument("number of death", IntegerArgumentType.integer()).executes(context -> {
final var source = context.getSource();
globalDifficultyGetter.get().setNumberOfDeath(IntegerArgumentType.getInteger(context, "number of death"), false);
GLOBAL_DIFFICULTY_GETTER.get().setNumberOfDeath(IntegerArgumentType.getInteger(context, "number of death"), false);
source.sendFeedback(() -> Text.literal("The difficulty has been changed"), true);
return Command.SINGLE_SUCCESS;
})
);

// is /dds set player [player] [difficulty|daily-death] [int]
final var setPlayerCommand = literal("player").then(argument("player", EntityArgumentType.player())
.then(
literal("difficulty").then(argument("number of death", IntegerArgumentType.integer()).executes(context -> {
final var source = context.getSource();
final var server = source.getServer();
final var target = EntityArgumentType.getPlayer(context, "player");
playerDifficultyGetter.get(server, target).setNumberOfDeath(IntegerArgumentType.getInteger(context, "number of death"), false);
source.sendFeedback(() -> {
return Text.literal("The difficulty has been changed for ").append(target.getDisplayName());
}, true);
target.sendMessage(Text.literal("Your difficulty has been changed by ").append(source.getDisplayName()));
return Command.SINGLE_SUCCESS;
}))
).then(
literal("daily-death").then(argument("number of death", IntegerArgumentType.integer()).executes(context -> {
context.getSource().sendFeedback(() -> Text.literal("Not implemented yet"), false);
final var source = context.getSource();
final var server = source.getServer();
final var target = EntityArgumentType.getPlayer(context, "player");
playerDifficultyGetter.get(server, target).setDeathDay(IntegerArgumentType.getInteger(context, "number of death"));
source.sendFeedback(() -> {
return Text.literal("The difficulty has been changed for ").append(target.getDisplayName());
}, true);
target.sendMessage(Text.literal("Your difficulty has been changed by ").append(source.getDisplayName()));
return Command.SINGLE_SUCCESS;
}))
));
.then(
literal("difficulty").then(argument("number of death", IntegerArgumentType.integer()).executes(context -> {
final var source = context.getSource();
final var server = source.getServer();
final var target = EntityArgumentType.getPlayer(context, "player");
PLAYER_DIFFICULTY_GETTER.get(server, target).setNumberOfDeath(IntegerArgumentType.getInteger(context, "number of death"), false);
source.sendFeedback(() -> {
return Text.literal("The difficulty has been changed for ").append(target.getDisplayName());
}, true);
target.sendMessage(Text.literal("Your difficulty has been changed by ").append(source.getDisplayName()));
return Command.SINGLE_SUCCESS;
}))
).then(
literal("daily-death").then(argument("number of death", IntegerArgumentType.integer()).executes(context -> {
context.getSource().sendFeedback(() -> Text.literal("Not implemented yet"), false);
final var source = context.getSource();
final var server = source.getServer();
final var target = EntityArgumentType.getPlayer(context, "player");
PLAYER_DIFFICULTY_GETTER.get(server, target).setDeathDay(IntegerArgumentType.getInteger(context, "number of death"));
source.sendFeedback(() -> {
return Text.literal("The difficulty has been changed for ").append(target.getDisplayName());
}, true);
target.sendMessage(Text.literal("Your difficulty has been changed by ").append(source.getDisplayName()));
return Command.SINGLE_SUCCESS;
}))
));

// is /dds set [global|player]
final var setCommand = literal("set")
Expand Down Expand Up @@ -150,7 +126,7 @@ private static int sendPlayerDifficulty(CommandContext<ServerCommandSource> cont
final var source = context.getSource();
final var server = source.getServer();
source.sendFeedback(() -> Text.literal(
playerDifficultyGetter.get(server, target)
PLAYER_DIFFICULTY_GETTER.get(server, target)
.getDifficultyUpdate(server.getOverworld().getDifficulty())
), false);
return Command.SINGLE_SUCCESS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class PlayerDifficultyManager extends DifficultyManager {

public static final int SECONDS_BEFORE_DECREASED = 24*60*60;

public static final Text KICKED_DIED_TOO_MUCH_MESSAGE = Text.of("You died too much during 24h...\nYou can log back in 12h.");

public static class HealthModifier extends PlayerHealthModifier {
public static final Identifier ID = Identifier.of(PREFIX + "player_health_modifier");

Expand Down Expand Up @@ -314,7 +316,7 @@ public boolean kickIfDiedTooMuch(ServerPlayNetworkHandler handler) {
resetDeathDay();
return false;
}
handler.disconnect(Text.of("You died too much during 24h...\nYou can log back in 12h."));
handler.disconnect(KICKED_DIED_TOO_MUCH_MESSAGE);
return true;
} else if (tempBan) {
tempBan = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package world.anhgelus.architectsland.difficultydeathscaler.mixin;

import com.mojang.authlib.GameProfile;
import net.minecraft.server.PlayerManager;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import world.anhgelus.architectsland.difficultydeathscaler.difficulty.player.PlayerDifficultyManager;

import java.net.SocketAddress;

import static world.anhgelus.architectsland.difficultydeathscaler.utils.Getters.PROFILE_DIFFICULTY_GETTER;

@Mixin(PlayerManager.class)
public abstract class PlayerManagerMixin {
@Inject(at = @At("HEAD"), method = "checkCanJoin", cancellable = true)
private void checkCanJoin(SocketAddress address, GameProfile profile, CallbackInfoReturnable<Text> cir) {
if (PROFILE_DIFFICULTY_GETTER == null) return;
final var difficulty = PROFILE_DIFFICULTY_GETTER.get(profile);
if (difficulty == null) return;
if (difficulty.diedTooMuch())
cir.setReturnValue(PlayerDifficultyManager.KICKED_DIED_TOO_MUCH_MESSAGE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package world.anhgelus.architectsland.difficultydeathscaler.utils;

import com.mojang.authlib.GameProfile;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import world.anhgelus.architectsland.difficultydeathscaler.difficulty.global.GlobalDifficultyManager;
import world.anhgelus.architectsland.difficultydeathscaler.difficulty.player.PlayerDifficultyManager;

public class Getters {
/**
* Functional interface giving the player difficulty manager with GameProfile
*/
@FunctionalInterface
public interface ProfileDifficultyGetter {
PlayerDifficultyManager get(GameProfile profile);
}

/**
* Functional interface giving the global difficulty manager
*/
@FunctionalInterface
public interface GlobalDifficultyGetter {
GlobalDifficultyManager get();
}

/**
* Functional interface giving the player difficulty manager
*/
@FunctionalInterface
public interface PlayerDifficultyGetter {
PlayerDifficultyManager get(MinecraftServer server, ServerPlayerEntity player);
}

public static Getters.ProfileDifficultyGetter PROFILE_DIFFICULTY_GETTER;

public static Getters.PlayerDifficultyGetter PLAYER_DIFFICULTY_GETTER;

public static Getters.GlobalDifficultyGetter GLOBAL_DIFFICULTY_GETTER;
}
3 changes: 2 additions & 1 deletion src/main/resources/difficultydeathscaler.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"AnnoyingDrowned",
"AnnoyingMobEntity",
"AnnoyingSkeleton",
"AnnoyingZombie"
"AnnoyingZombie",
"PlayerManagerMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit 4773ff8

Please sign in to comment.