Initial port of 1.18.2-3.0.1 to 1.19.2.
This commit is contained in:
8
.gitattributes
vendored
Normal file
8
.gitattributes
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*.blend filter=lfs diff=lfs merge=lfs -text
|
||||
*.obj filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.kra filter=lfs diff=lfs merge=lfs -text
|
||||
*.mtl filter=lfs diff=lfs merge=lfs -text
|
||||
*.bbmodel filter=lfs diff=lfs merge=lfs -text
|
||||
*.ogg filter=lfs diff=lfs merge=lfs -text
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/.gradle/
|
||||
/.idea/
|
||||
/build/
|
||||
/run/
|
||||
/src/test/
|
||||
/src/generated/resources/.cache/cache
|
125
build.gradle
Normal file
125
build.gradle
Normal file
@ -0,0 +1,125 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
// These repositories are only for Gradle plugins, put any other repositories in the repository block further below
|
||||
maven { url = 'https://maven.minecraftforge.net' }
|
||||
maven { url = 'https://repo.spongepowered.org/repository/maven-public/' }
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
|
||||
classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
apply plugin: 'org.spongepowered.mixin'
|
||||
|
||||
def archiveVersion = "${project.mcVersion}-${project.buildVersion}" as Object
|
||||
|
||||
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
|
||||
|
||||
minecraft {
|
||||
mappings channel: 'official', version: mcVersion
|
||||
|
||||
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
|
||||
runs {
|
||||
client {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
arg "-mixin.config=${modID}.mixins.json"
|
||||
property 'mixin.env.remapRefMap', 'true'
|
||||
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
|
||||
|
||||
mods {
|
||||
loginprotection {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
arg "-mixin.config=${modID}.mixins.json"
|
||||
property 'mixin.env.remapRefMap', 'true'
|
||||
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
|
||||
|
||||
mods {
|
||||
loginprotection {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
arg "-mixin.config=${modID}.mixins.json"
|
||||
property 'mixin.env.remapRefMap', 'true'
|
||||
property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg"
|
||||
|
||||
args '--mod', 'loginprotection', '--all',
|
||||
'--existing', file('src/main/resources').toString(),
|
||||
'--existing', file('src/generated/resources').toString(),
|
||||
'--output', file('src/generated/resources/')
|
||||
|
||||
mods {
|
||||
loginprotection {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mixin {
|
||||
add sourceSets.main, "${modID}.refmap.json"
|
||||
config "${modID}.mixins.json"
|
||||
}
|
||||
|
||||
sourceSets.main.resources {
|
||||
srcDir 'src/generated/resources'
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "Progwml6 maven"
|
||||
url = "https://dvs1.progwml6.com/files/maven/"
|
||||
}
|
||||
maven {
|
||||
name = "ModMaven"
|
||||
url = "https://modmaven.dev"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "net.minecraftforge:forge:${project.mcVersion}-${project.forgeVersion}"
|
||||
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
|
||||
}
|
||||
|
||||
jar {
|
||||
archiveFileName = "${project.archivesBaseName}-${archiveVersion}.jar"
|
||||
manifest {
|
||||
attributes([
|
||||
"Specification-Title" : project.name,
|
||||
"Specification-Vendor" : project.author,
|
||||
"Specification-Version" : "1",
|
||||
"Implementation-Title" : project.name,
|
||||
"Implementation-Vendor" : project.author,
|
||||
"Implementation-Version" : archiveVersion,
|
||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
jar.finalizedBy('reobfJar')
|
12
gradle.properties
Normal file
12
gradle.properties
Normal file
@ -0,0 +1,12 @@
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=false
|
||||
|
||||
group = dev.micle
|
||||
archivesBaseName = micles-login-protection-forge
|
||||
modID = loginprotection
|
||||
name = Micle's Login Protection
|
||||
author = Micle
|
||||
|
||||
buildVersion = 3.0.0
|
||||
mcVersion = 1.19.2
|
||||
forgeVersion = 43.1.47
|
1
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
1
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1 @@
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
1
settings.gradle
Normal file
1
settings.gradle
Normal file
@ -0,0 +1 @@
|
||||
rootProject.name = 'LoginProtection-1.19'
|
43
src/main/java/dev/micle/loginprotection/LoginProtection.java
Normal file
43
src/main/java/dev/micle/loginprotection/LoginProtection.java
Normal file
@ -0,0 +1,43 @@
|
||||
package dev.micle.loginprotection;
|
||||
|
||||
import dev.micle.loginprotection.proxy.IProxy;
|
||||
import dev.micle.loginprotection.proxy.Proxy;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Mod(LoginProtection.MOD_ID)
|
||||
public class LoginProtection {
|
||||
public static final String MOD_ID = "loginprotection";
|
||||
private static IProxy proxy;
|
||||
|
||||
public LoginProtection() {
|
||||
proxy = DistExecutor.safeRunForDist(
|
||||
() -> Proxy.Client::new,
|
||||
() -> Proxy.Server::new
|
||||
);
|
||||
}
|
||||
|
||||
public static ResourceLocation createResourceLocation(String name) throws IllegalArgumentException {
|
||||
if (name.contains(":")) {
|
||||
throw new IllegalArgumentException("Name contains namespace!");
|
||||
}
|
||||
return new ResourceLocation(MOD_ID, name);
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
Optional<? extends ModContainer> modContainer = ModList.get().getModContainerById(MOD_ID);
|
||||
if (modContainer.isPresent()) {
|
||||
return modContainer.get().getModInfo().getVersion().toString();
|
||||
}
|
||||
return "0.0.0";
|
||||
}
|
||||
|
||||
public static IProxy getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package dev.micle.loginprotection.data;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ProtectedPlayer {
|
||||
// Initialize variables
|
||||
private final UUID playerUUID;
|
||||
private final Timer timer = new Timer();
|
||||
private TimerTask afkTimerTask, gracePeriodTimerTask;
|
||||
private State state;
|
||||
|
||||
/**
|
||||
* Constructor for a ProtectedPlayer.
|
||||
* @param playerUUID UUID of player to use.
|
||||
*/
|
||||
public ProtectedPlayer(UUID playerUUID, State state) {
|
||||
this.playerUUID = playerUUID;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UUID of player,
|
||||
*/
|
||||
public UUID getPlayerUUID() {
|
||||
return playerUUID;
|
||||
}
|
||||
|
||||
public Timer getTimer() {
|
||||
return timer;
|
||||
}
|
||||
|
||||
public void setGracePeriodTimerTask(TimerTask gracePeriodTimerTask, long delay) {
|
||||
if (this.gracePeriodTimerTask != null) {
|
||||
this.gracePeriodTimerTask.cancel();
|
||||
}
|
||||
if (gracePeriodTimerTask != null) {
|
||||
this.gracePeriodTimerTask = gracePeriodTimerTask;
|
||||
timer.schedule(this.gracePeriodTimerTask, delay);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAfkTimerTask(TimerTask afkTimerTask, long delay) {
|
||||
if (this.afkTimerTask != null) {
|
||||
this.afkTimerTask.cancel();
|
||||
}
|
||||
if (afkTimerTask != null) {
|
||||
this.afkTimerTask = afkTimerTask;
|
||||
timer.schedule(this.afkTimerTask, delay);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current state of the player.
|
||||
*/
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of the player.
|
||||
* @param state Player's new state.
|
||||
*/
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public enum State {
|
||||
JOINING,
|
||||
AFK,
|
||||
ACTIVE,
|
||||
LOGIN_GRACE,
|
||||
AFK_GRACE
|
||||
}
|
||||
}
|
@ -0,0 +1,234 @@
|
||||
package dev.micle.loginprotection.data;
|
||||
|
||||
import dev.micle.loginprotection.LoginProtection;
|
||||
import dev.micle.loginprotection.network.NetworkManager;
|
||||
import dev.micle.loginprotection.network.server.PlayerStatePacket;
|
||||
import dev.micle.loginprotection.network.server.RequestLastInputTickPacket;
|
||||
import dev.micle.loginprotection.setup.Config;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ProtectedPlayerManager {
|
||||
// Initialize variables
|
||||
private static final List<ProtectedPlayer> protectedPlayers = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Method for initializing the ProtectedPlayerManager.
|
||||
*/
|
||||
public static void init() {
|
||||
for (ProtectedPlayer protectedPlayer : protectedPlayers) {
|
||||
removePlayer(protectedPlayer.getPlayerUUID());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a player to be protected.
|
||||
* @param playerUUID UUID of player to protect.
|
||||
*/
|
||||
public static void addPlayer(UUID playerUUID) {
|
||||
if (getPlayer(playerUUID) != null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
protectedPlayers.add(new ProtectedPlayer(playerUUID, ProtectedPlayer.State.JOINING));
|
||||
NetworkManager.getChannel().sendTo(new PlayerStatePacket(ProtectedPlayer.State.JOINING),
|
||||
LoginProtection.getProxy().getServer().getPlayerList().getPlayer(playerUUID).connection.getConnection(),
|
||||
NetworkDirection.PLAY_TO_CLIENT);
|
||||
} catch (NullPointerException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a protected player from the list of protected players.
|
||||
* @param playerUUID UUID of player to get.
|
||||
* @return ProtectedPlayer instance if player is present, otherwise null.
|
||||
*/
|
||||
public static ProtectedPlayer getPlayer(UUID playerUUID) {
|
||||
for (ProtectedPlayer protectedPlayer : protectedPlayers) {
|
||||
if (protectedPlayer.getPlayerUUID().equals(playerUUID)) {
|
||||
return protectedPlayer;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a player from the list of protected players.
|
||||
* @param playerUUID UUID of player to remove.
|
||||
*/
|
||||
public static void removePlayer(UUID playerUUID) {
|
||||
ProtectedPlayer player = getPlayer(playerUUID);
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.getTimer().cancel();
|
||||
protectedPlayers.remove(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a player's state appropriately.
|
||||
* @param playerUUID UUID of player to update the state of.
|
||||
*/
|
||||
public static void updateState(UUID playerUUID) {
|
||||
ProtectedPlayer protectedPlayer = getPlayer(playerUUID);
|
||||
ServerPlayer player = LoginProtection.getProxy().getServer().getPlayerList().getPlayer(playerUUID);
|
||||
if (player == null) {
|
||||
removePlayer(playerUUID);
|
||||
return;
|
||||
}
|
||||
|
||||
if (protectedPlayer == null) {
|
||||
addPlayer(playerUUID);
|
||||
} else {
|
||||
ProtectedPlayer.State currentState = protectedPlayer.getState();
|
||||
if (currentState.equals(ProtectedPlayer.State.JOINING)) {
|
||||
if (Config.Server.LOGIN_GRACE_ENABLED.get()) {
|
||||
// JOINING -> LOGIN_GRACE
|
||||
protectedPlayer.setState(ProtectedPlayer.State.LOGIN_GRACE);
|
||||
startGraceTimer(playerUUID, Config.Server.LOGIN_GRACE_DURATION.get() * 1000);
|
||||
} else {
|
||||
// JOINING -> ACTIVE
|
||||
protectedPlayer.setState(ProtectedPlayer.State.ACTIVE);
|
||||
if (Config.Server.LOGIN_APPLY_POST_EFFECTS.get()) {
|
||||
applyPostEffects(playerUUID);
|
||||
}
|
||||
if (Config.Server.AFK_PROTECTION_ENABLED.get()) {
|
||||
startAfkTimer(playerUUID, Config.Server.AFK_TIME_THRESHOLD.get() * 1000);
|
||||
} else {
|
||||
removePlayer(playerUUID);
|
||||
}
|
||||
}
|
||||
} else if (currentState.equals(ProtectedPlayer.State.LOGIN_GRACE) ||
|
||||
currentState.equals(ProtectedPlayer.State.AFK_GRACE)) {
|
||||
// LOGIN_GRACE, AFK_GRACE -> ACTIVE
|
||||
protectedPlayer.setState(ProtectedPlayer.State.ACTIVE);
|
||||
if ((currentState.equals(ProtectedPlayer.State.LOGIN_GRACE) && Config.Server.LOGIN_APPLY_POST_EFFECTS.get()) ||
|
||||
(currentState.equals(ProtectedPlayer.State.AFK_GRACE) && Config.Server.AFK_APPLY_POST_EFFECTS.get())) {
|
||||
applyPostEffects(playerUUID);
|
||||
}
|
||||
if (Config.Server.AFK_PROTECTION_ENABLED.get()) {
|
||||
startAfkTimer(playerUUID, Config.Server.AFK_TIME_THRESHOLD.get() * 1000);
|
||||
} else {
|
||||
removePlayer(playerUUID);
|
||||
}
|
||||
} else if (currentState.equals(ProtectedPlayer.State.ACTIVE)) {
|
||||
// ACTIVE -> AFK
|
||||
protectedPlayer.setState(ProtectedPlayer.State.AFK);
|
||||
} else if (currentState.equals(ProtectedPlayer.State.AFK)) {
|
||||
if (Config.Server.AFK_GRACE_ENABLED.get()) {
|
||||
// AFK -> AFK_GRACE
|
||||
protectedPlayer.setState(ProtectedPlayer.State.AFK_GRACE);
|
||||
startGraceTimer(playerUUID, Config.Server.AFK_GRACE_DURATION.get() * 1000);
|
||||
} else {
|
||||
// AFK -> ACTIVE
|
||||
protectedPlayer.setState(ProtectedPlayer.State.ACTIVE);
|
||||
if (Config.Server.AFK_APPLY_POST_EFFECTS.get()) {
|
||||
applyPostEffects(playerUUID);
|
||||
}
|
||||
if (Config.Server.AFK_PROTECTION_ENABLED.get()) {
|
||||
startAfkTimer(playerUUID, Config.Server.AFK_TIME_THRESHOLD.get() * 1000);
|
||||
} else {
|
||||
removePlayer(playerUUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send state packet to player
|
||||
NetworkManager.getChannel().sendTo(new PlayerStatePacket(protectedPlayer.getState()),
|
||||
player.connection.getConnection(),
|
||||
NetworkDirection.PLAY_TO_CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the afk timer for a given player if they are a protected player.
|
||||
* @param playerUUID The UUID of the player.
|
||||
* @param delay After how much time should the task run? (in milliseconds)
|
||||
*/
|
||||
public static void startAfkTimer(UUID playerUUID, long delay) {
|
||||
ProtectedPlayer player = getPlayer(playerUUID);
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create scheduled task
|
||||
player.setAfkTimerTask(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Send request for list input tick packet to player
|
||||
NetworkManager.getChannel().sendTo(new RequestLastInputTickPacket(),
|
||||
LoginProtection.getProxy().getServer().getPlayerList().getPlayer(playerUUID).connection.getConnection(),
|
||||
NetworkDirection.PLAY_TO_CLIENT);
|
||||
} catch (NullPointerException e) {
|
||||
removePlayer(playerUUID);
|
||||
}
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the grace period timer for a given player if they are a protected player.
|
||||
* @param playerUUID UUID of the player.
|
||||
* @param delay How long should the grace period last? (in milliseconds)
|
||||
*/
|
||||
private static void startGraceTimer(UUID playerUUID, long delay) {
|
||||
ProtectedPlayer player = getPlayer(playerUUID);
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create scheduled task
|
||||
player.setGracePeriodTimerTask(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Update player state
|
||||
updateState(playerUUID);
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies effects to the player.
|
||||
* @param playerUUID UUID of player to apply effects to.
|
||||
*/
|
||||
private static void applyPostEffects(UUID playerUUID) {
|
||||
// Get player entity
|
||||
Player player = LoginProtection.getProxy().getServer().getPlayerList().getPlayer(playerUUID);
|
||||
if (player == null) {
|
||||
removePlayer(playerUUID);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply effects
|
||||
if (player.isInWater()) {
|
||||
if (Config.Server.POST_REFILL_AIR_ENABLED.get()) {
|
||||
player.setAirSupply(player.getMaxAirSupply());
|
||||
}
|
||||
if (Config.Server.POST_WATER_ENABLED.get()) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING,
|
||||
Config.Server.POST_WATER_DURATION.get() * 20, 0));
|
||||
}
|
||||
}
|
||||
if (player.isInLava()) {
|
||||
if (Config.Server.POST_LAVA_ENABLED.get()) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE,
|
||||
Config.Server.POST_LAVA_DURATION.get()*20, 0));
|
||||
}
|
||||
}
|
||||
if (player.isOnFire()) {
|
||||
if (Config.Server.POST_FIRE_ENABLED.get()) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE,
|
||||
Config.Server.POST_FIRE_DURATION.get()*20, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,345 @@
|
||||
package dev.micle.loginprotection.events.client;
|
||||
|
||||
import dev.micle.loginprotection.data.ProtectedPlayer;
|
||||
import dev.micle.loginprotection.network.NetworkManager;
|
||||
import dev.micle.loginprotection.network.client.InputPacket;
|
||||
import dev.micle.loginprotection.proxy.Proxy;
|
||||
import dev.micle.loginprotection.setup.Config;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.Options;
|
||||
import net.minecraft.client.gui.screens.ChatScreen;
|
||||
import net.minecraft.client.gui.screens.PauseScreen;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.gui.screens.inventory.InventoryScreen;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.event.InputEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class OnClientInputEventHandler {
|
||||
private static boolean isPausePressed = false;
|
||||
private static boolean isDebugPressed = false;
|
||||
private static boolean isFullscreenPressed = false;
|
||||
private static boolean isTogglePerspectivePressed = false;
|
||||
private static boolean isSmoothCameraPressed = false;
|
||||
private static boolean isScreenshotPressed = false;
|
||||
private static boolean isSpectatorOutlinesPressed = false;
|
||||
private static boolean isAdvancementsPressed = false;
|
||||
private static boolean isPlayerListPressed = false;
|
||||
private static boolean isChatPressed = false;
|
||||
private static boolean isChatCommandPressed = false;
|
||||
private static boolean isChatEnterPressed = false;
|
||||
private static boolean isSocialInteractionsPressed = false;
|
||||
private static boolean isLoadHotbarActivatorPressed = false;
|
||||
private static boolean isSaveHotbarActivatorPressed = false;
|
||||
private static boolean isSwapOffhandPressed = false;
|
||||
private static boolean isInventoryPressed = false;
|
||||
private static boolean isDropItemPressed = false;
|
||||
private static boolean isUseItemPressed = false;
|
||||
private static boolean isPickBlockPressed = false;
|
||||
private static boolean isAttackPressed = false;
|
||||
private static boolean isMoveUpPressed = false;
|
||||
private static boolean isMoveRightPressed = false;
|
||||
private static boolean isMoveDownPressed = false;
|
||||
private static boolean isMoveLeftPressed = false;
|
||||
private static boolean isMoveSprintPressed = false;
|
||||
private static boolean isSneakPressed = false;
|
||||
private static boolean isJumpPressed = false;
|
||||
private static final Boolean[] isHotBarPressed = new Boolean[9];
|
||||
|
||||
private static Screen previousScreen = null;
|
||||
|
||||
public OnClientInputEventHandler() {
|
||||
// Initialize isHotBarPressed to false
|
||||
Arrays.fill(isHotBarPressed, false);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void KeyInputEvent(InputEvent.KeyInputEvent event) {
|
||||
handle(event.getAction(), event.getKey());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void MouseInputEvent(InputEvent.MouseInputEvent event) {
|
||||
handle(event.getAction(), event.getButton());
|
||||
}
|
||||
|
||||
private static void handle(int action, int key) {
|
||||
// Initialize variables
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
|
||||
// Cancel event if not in a game
|
||||
if ((minecraft.getCurrentServer() == null && minecraft.getSingleplayerServer() == null) ||
|
||||
Proxy.Client.getPlayerState() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if input is a press or release
|
||||
if (action == GLFW.GLFW_PRESS || action == GLFW.GLFW_RELEASE) {
|
||||
// Initialize variables
|
||||
Options keyBinds = minecraft.options;
|
||||
boolean isPressed = action == GLFW.GLFW_PRESS;
|
||||
List<String> allowedKeys = (Proxy.Client.getPlayerState().equals(ProtectedPlayer.State.JOINING)) ?
|
||||
(List<String>) Config.Server.LOGIN_KEY_ALLOW_LIST.get() :
|
||||
(List<String>) Config.Server.AFK_KEY_ALLOW_LIST.get();
|
||||
|
||||
// Check if the key is monitored, save it's state, update last input tick and notify server if not allowed
|
||||
if (key == GLFW.GLFW_KEY_ESCAPE) {
|
||||
isPausePressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.PAUSE.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == GLFW.GLFW_KEY_F3) {
|
||||
isDebugPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.DEBUG.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyFullscreen.getKey().getValue()) {
|
||||
isFullscreenPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.FULLSCREEN.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyTogglePerspective.getKey().getValue()) {
|
||||
isTogglePerspectivePressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.PERSPECTIVE.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keySmoothCamera.getKey().getValue()) {
|
||||
isSmoothCameraPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.SMOOTH_CAMERA.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyScreenshot.getKey().getValue()) {
|
||||
isScreenshotPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.SCREENSHOT.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keySpectatorOutlines.getKey().getValue()) {
|
||||
isSpectatorOutlinesPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.SPECTATOR_OUTLINES.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyAdvancements.getKey().getValue()) {
|
||||
isAdvancementsPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.ADVANCEMENTS.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyPlayerList.getKey().getValue()) {
|
||||
isPlayerListPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.PLAYER_LIST.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyChat.getKey().getValue()) {
|
||||
isChatPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.CHAT.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyCommand.getKey().getValue()) {
|
||||
isChatCommandPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.CHAT.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == GLFW.GLFW_KEY_ENTER) {
|
||||
isChatEnterPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.CHAT.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keySocialInteractions.getKey().getValue()) {
|
||||
isSocialInteractionsPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.SOCIAL_INTERACTIONS.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyLoadHotbarActivator.getKey().getValue()) {
|
||||
isLoadHotbarActivatorPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.LOAD_HOTBAR_ACTIVATOR.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keySaveHotbarActivator.getKey().getValue()) {
|
||||
isSaveHotbarActivatorPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.SAVE_HOTBAR_ACTIVATOR.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keySwapOffhand.getKey().getValue()) {
|
||||
isSwapOffhandPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.SWAP_ITEM.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyInventory.getKey().getValue()) {
|
||||
isInventoryPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.INVENTORY.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyDrop.getKey().getValue()) {
|
||||
isDropItemPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.DROP_ITEM.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyUse.getKey().getValue()) {
|
||||
isUseItemPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.USE_ITEM.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyPickItem.getKey().getValue()) {
|
||||
isPickBlockPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.PICK_BLOCK.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyAttack.getKey().getValue()) {
|
||||
isAttackPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.ATTACK.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyUp.getKey().getValue()) {
|
||||
isMoveUpPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.MOVE.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyRight.getKey().getValue()) {
|
||||
isMoveRightPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.MOVE.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyDown.getKey().getValue()) {
|
||||
isMoveDownPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.MOVE.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyLeft.getKey().getValue()) {
|
||||
isMoveLeftPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.MOVE.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keySprint.getKey().getValue()) {
|
||||
isMoveSprintPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.MOVE.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyShift.getKey().getValue()) {
|
||||
isSneakPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.SNEAK.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else if (key == keyBinds.keyJump.getKey().getValue()) {
|
||||
isJumpPressed = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.JUMP.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < isHotBarPressed.length; i++) {
|
||||
if (key == keyBinds.keyHotbarSlots[i].getKey().getValue()) {
|
||||
isHotBarPressed[i] = isPressed;
|
||||
if (!checkIfScreenIsAllowed(allowedKeys, minecraft.screen, !isPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.HOTBAR.toString())) {
|
||||
updateAndNotify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkIfScreenIsAllowed(List<String> allowedKeys, Screen screen, boolean isActionReleased) {
|
||||
// Initialize variables
|
||||
boolean isAllowed;
|
||||
|
||||
// Check if the previous screen or the current screen are significant and their respective keys are allowed
|
||||
if (previousScreen instanceof PauseScreen || screen instanceof PauseScreen) {
|
||||
isAllowed = allowedKeys.contains(Config.Server.KEYS.PAUSE.toString());
|
||||
} else if (previousScreen instanceof InventoryScreen || screen instanceof InventoryScreen) {
|
||||
isAllowed = allowedKeys.contains(Config.Server.KEYS.INVENTORY.toString());
|
||||
} else if (previousScreen instanceof ChatScreen || screen instanceof ChatScreen) {
|
||||
isAllowed = allowedKeys.contains(Config.Server.KEYS.CHAT.toString());
|
||||
} else {
|
||||
// Allow any other screen that is not the game itself
|
||||
isAllowed = screen != null;
|
||||
}
|
||||
|
||||
// Only update the previous screen when key is released
|
||||
if (isActionReleased) {
|
||||
previousScreen = screen;
|
||||
}
|
||||
|
||||
// Return value
|
||||
return isAllowed;
|
||||
}
|
||||
|
||||
private static void updateAndNotify() {
|
||||
// Update last input tick
|
||||
Proxy.Client.updateLastInputTick();
|
||||
|
||||
// Send an input packet if player is joining or is afk
|
||||
if (Proxy.Client.getPlayerState().equals(ProtectedPlayer.State.JOINING) ||
|
||||
Proxy.Client.getPlayerState().equals(ProtectedPlayer.State.AFK)) {
|
||||
NetworkManager.getChannel().sendToServer(new InputPacket());
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkIfInputIsAllowed() {
|
||||
// Get list of allowed keys
|
||||
List<String> allowedKeys = (Proxy.Client.getPlayerState().equals(ProtectedPlayer.State.JOINING)) ?
|
||||
(List<String>) Config.Server.LOGIN_KEY_ALLOW_LIST.get() :
|
||||
(List<String>) Config.Server.AFK_KEY_ALLOW_LIST.get();
|
||||
|
||||
// Update last input tick and notify server if any of the monitored keys are pressed and not allowed
|
||||
if ((isPausePressed && !allowedKeys.contains(Config.Server.KEYS.PAUSE.toString())) ||
|
||||
(isDebugPressed && !allowedKeys.contains(Config.Server.KEYS.DEBUG.toString())) ||
|
||||
(isFullscreenPressed && !allowedKeys.contains(Config.Server.KEYS.FULLSCREEN.toString())) ||
|
||||
(isTogglePerspectivePressed && !allowedKeys.contains(Config.Server.KEYS.PERSPECTIVE.toString())) ||
|
||||
(isSmoothCameraPressed && !allowedKeys.contains(Config.Server.KEYS.SMOOTH_CAMERA.toString())) ||
|
||||
(isScreenshotPressed && !allowedKeys.contains(Config.Server.KEYS.SCREENSHOT.toString())) ||
|
||||
(isSpectatorOutlinesPressed && !allowedKeys.contains(Config.Server.KEYS.SPECTATOR_OUTLINES.toString())) ||
|
||||
(isAdvancementsPressed && !allowedKeys.contains(Config.Server.KEYS.ADVANCEMENTS.toString())) ||
|
||||
(isPlayerListPressed && !allowedKeys.contains(Config.Server.KEYS.PLAYER_LIST.toString())) ||
|
||||
((isChatPressed || isChatCommandPressed || isChatEnterPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.CHAT.toString())) ||
|
||||
(isSocialInteractionsPressed && !allowedKeys.contains(Config.Server.KEYS.SOCIAL_INTERACTIONS.toString())) ||
|
||||
(isLoadHotbarActivatorPressed && !allowedKeys.contains(Config.Server.KEYS.LOAD_HOTBAR_ACTIVATOR.toString())) ||
|
||||
(isSaveHotbarActivatorPressed && !allowedKeys.contains(Config.Server.KEYS.SAVE_HOTBAR_ACTIVATOR.toString())) ||
|
||||
(isSwapOffhandPressed && !allowedKeys.contains(Config.Server.KEYS.SWAP_ITEM.toString())) ||
|
||||
(isInventoryPressed && !allowedKeys.contains(Config.Server.KEYS.INVENTORY.toString())) ||
|
||||
(isDropItemPressed && !allowedKeys.contains(Config.Server.KEYS.DROP_ITEM.toString())) ||
|
||||
(isUseItemPressed && !allowedKeys.contains(Config.Server.KEYS.USE_ITEM.toString())) ||
|
||||
(isPickBlockPressed && !allowedKeys.contains(Config.Server.KEYS.PICK_BLOCK.toString())) ||
|
||||
(isAttackPressed && !allowedKeys.contains(Config.Server.KEYS.ATTACK.toString())) ||
|
||||
((isMoveUpPressed || isMoveRightPressed || isMoveDownPressed || isMoveLeftPressed || isMoveSprintPressed) &&
|
||||
!allowedKeys.contains(Config.Server.KEYS.MOVE.toString())) ||
|
||||
(isSneakPressed && !allowedKeys.contains(Config.Server.KEYS.SNEAK.toString())) ||
|
||||
(isJumpPressed && !allowedKeys.contains(Config.Server.KEYS.JUMP.toString())) ||
|
||||
(Arrays.stream(isHotBarPressed).anyMatch(b -> b) && !allowedKeys.contains(Config.Server.KEYS.HOTBAR.toString()))) {
|
||||
updateAndNotify();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package dev.micle.loginprotection.events.common;
|
||||
|
||||
import dev.micle.loginprotection.data.ProtectedPlayer;
|
||||
import dev.micle.loginprotection.data.ProtectedPlayerManager;
|
||||
import dev.micle.loginprotection.setup.Config;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
public class OnLivingSetAttackTargetEventHandler {
|
||||
@SubscribeEvent
|
||||
public void LivingSetAttackTargetEvent(LivingSetAttackTargetEvent event) {
|
||||
if (!(event.getTarget() instanceof Player target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProtectedPlayer player = ProtectedPlayerManager.getPlayer(target.getUUID());
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if mob should ignore player
|
||||
if ((player.getState().equals(ProtectedPlayer.State.JOINING) && Config.Server.LOGIN_MOBS_IGNORE_PLAYER.get()) ||
|
||||
(player.getState().equals(ProtectedPlayer.State.AFK) && Config.Server.AFK_MOBS_IGNORE_PLAYER.get()) ||
|
||||
(player.getState().equals(ProtectedPlayer.State.LOGIN_GRACE) && Config.Server.LOGIN_GRACE_MOBS_IGNORE_PLAYER.get()) ||
|
||||
(player.getState().equals(ProtectedPlayer.State.AFK_GRACE) && Config.Server.AFK_GRACE_MOBS_IGNORE_PLAYER.get())) {
|
||||
((Mob) event.getEntityLiving()).setTarget(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package dev.micle.loginprotection.events.common;
|
||||
|
||||
import dev.micle.loginprotection.data.ProtectedPlayer;
|
||||
import dev.micle.loginprotection.data.ProtectedPlayerManager;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.event.entity.living.LivingDamageEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
public class OnPlayerDamageEventHandler {
|
||||
@SubscribeEvent
|
||||
public void LivingDamageEvent(LivingDamageEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProtectedPlayer protectedPlayer = ProtectedPlayerManager.getPlayer(player.getUUID());
|
||||
if (protectedPlayer == null || protectedPlayer.getState().equals(ProtectedPlayer.State.ACTIVE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package dev.micle.loginprotection.events.common;
|
||||
|
||||
import dev.micle.loginprotection.data.ProtectedPlayerManager;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
public class OnPlayerJoinEventHandler {
|
||||
@SubscribeEvent
|
||||
public void EntityJoinWorldEvent(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProtectedPlayerManager.addPlayer(player.getUUID());
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package dev.micle.loginprotection.events.common;
|
||||
|
||||
import dev.micle.loginprotection.data.ProtectedPlayerManager;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
public class OnPlayerLeaveEventHandler {
|
||||
@SubscribeEvent
|
||||
public void PlayerLeaveEvent(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
if (!(event.getEntity() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProtectedPlayerManager.removePlayer(player.getUUID());
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package dev.micle.loginprotection.mixin;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dev.micle.loginprotection.data.ProtectedPlayer;
|
||||
import dev.micle.loginprotection.proxy.Proxy;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.gui.ForgeIngameGui;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ForgeIngameGui.class)
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class GuiRenderTickMixin {
|
||||
@Inject(method = "render", at = @At(value = "HEAD"))
|
||||
private void onClientTick(PoseStack poseStack, float partialTicks, CallbackInfo callbackInfo) {
|
||||
// Setup
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(Minecraft.getInstance().getWindow().getGuiScaledWidth() / 2.0,
|
||||
Minecraft.getInstance().getWindow().getGuiScaledHeight() / 2.0, 0);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
|
||||
// Render player state text
|
||||
poseStack.pushPose();
|
||||
poseStack.scale(5, 5, 5);
|
||||
|
||||
// Check if we should draw the state
|
||||
if (Proxy.Client.getPlayerState() != null && !Proxy.Client.getPlayerState().equals(ProtectedPlayer.State.ACTIVE)) {
|
||||
// Initialize variables
|
||||
Font font = Minecraft.getInstance().font;
|
||||
float offsetX = -(font.width(Proxy.Client.getPlayerState().toString()) / 2f);
|
||||
float offsetY = -((font.lineHeight / 2f) + ((Minecraft.getInstance().getWindow().getGuiScaledHeight() / 4f) / 5));
|
||||
int argb = 0xFFFFFFFF;
|
||||
|
||||
// Draw the player's protection state
|
||||
font.drawShadow(poseStack, Proxy.Client.getPlayerState().toString().replace("_", " "), offsetX, offsetY, argb);
|
||||
}
|
||||
poseStack.popPose();
|
||||
|
||||
// Finish
|
||||
RenderSystem.disableBlend();
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package dev.micle.loginprotection.network;
|
||||
|
||||
import dev.micle.loginprotection.LoginProtection;
|
||||
import dev.micle.loginprotection.network.client.InputPacket;
|
||||
import dev.micle.loginprotection.network.client.LastInputTickPacket;
|
||||
import dev.micle.loginprotection.network.server.PlayerStatePacket;
|
||||
import dev.micle.loginprotection.network.server.RequestLastInputTickPacket;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
|
||||
public class NetworkManager {
|
||||
private static SimpleChannel channel;
|
||||
|
||||
public static void init() {
|
||||
// Create channel
|
||||
channel = NetworkRegistry.ChannelBuilder.named(LoginProtection.createResourceLocation("network"))
|
||||
.clientAcceptedVersions(v -> v.equals(LoginProtection.getVersion()))
|
||||
.serverAcceptedVersions(v -> v.equals(LoginProtection.getVersion()))
|
||||
.networkProtocolVersion(LoginProtection::getVersion)
|
||||
.simpleChannel();
|
||||
|
||||
// Register packets
|
||||
int id = 0;
|
||||
channel.messageBuilder(InputPacket.class, id++)
|
||||
.encoder(InputPacket::encode)
|
||||
.decoder(InputPacket::decode)
|
||||
.consumer(InputPacket::handle)
|
||||
.add();
|
||||
channel.messageBuilder(PlayerStatePacket.class, id++)
|
||||
.encoder(PlayerStatePacket::encode)
|
||||
.decoder(PlayerStatePacket::decode)
|
||||
.consumer(PlayerStatePacket::handle)
|
||||
.add();
|
||||
channel.messageBuilder(RequestLastInputTickPacket.class, id++)
|
||||
.encoder(RequestLastInputTickPacket::encode)
|
||||
.decoder(RequestLastInputTickPacket::decode)
|
||||
.consumer(RequestLastInputTickPacket::handle)
|
||||
.add();
|
||||
channel.messageBuilder(LastInputTickPacket.class, id++)
|
||||
.encoder(LastInputTickPacket::encode)
|
||||
.decoder(LastInputTickPacket::decode)
|
||||
.consumer(LastInputTickPacket::handle)
|
||||
.add();
|
||||
}
|
||||
|
||||
public static SimpleChannel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package dev.micle.loginprotection.network.client;
|
||||
|
||||
import dev.micle.loginprotection.data.ProtectedPlayer;
|
||||
import dev.micle.loginprotection.data.ProtectedPlayerManager;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class InputPacket {
|
||||
public static void encode(final InputPacket packet, final FriendlyByteBuf buffer) {}
|
||||
|
||||
public static InputPacket decode(final FriendlyByteBuf buffer) {
|
||||
return new InputPacket();
|
||||
}
|
||||
|
||||
public static void handle(final InputPacket packet, final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
final NetworkEvent.Context context = contextSupplier.get();
|
||||
context.enqueueWork(() -> {
|
||||
// Get sender
|
||||
ServerPlayer sender = context.getSender();
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get protected player
|
||||
ProtectedPlayer protectedPlayer = ProtectedPlayerManager.getPlayer(sender.getUUID());
|
||||
if (protectedPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update player state if they are joining or afk
|
||||
if (protectedPlayer.getState().equals(ProtectedPlayer.State.JOINING) ||
|
||||
protectedPlayer.getState().equals(ProtectedPlayer.State.AFK)) {
|
||||
ProtectedPlayerManager.updateState(protectedPlayer.getPlayerUUID());
|
||||
}
|
||||
});
|
||||
context.setPacketHandled(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package dev.micle.loginprotection.network.client;
|
||||
|
||||
import dev.micle.loginprotection.data.ProtectedPlayer;
|
||||
import dev.micle.loginprotection.data.ProtectedPlayerManager;
|
||||
import dev.micle.loginprotection.proxy.Proxy;
|
||||
import dev.micle.loginprotection.setup.Config;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class LastInputTickPacket {
|
||||
private final int lastInputTick;
|
||||
|
||||
public LastInputTickPacket() {
|
||||
this(Proxy.Client.getLastInputTick());
|
||||
}
|
||||
public LastInputTickPacket(int lastInputTick) {
|
||||
this.lastInputTick = lastInputTick;
|
||||
}
|
||||
|
||||
public static void encode(final LastInputTickPacket packet, final FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(packet.lastInputTick);
|
||||
}
|
||||
|
||||
public static LastInputTickPacket decode(final FriendlyByteBuf buffer) {
|
||||
return new LastInputTickPacket(buffer.readInt());
|
||||
}
|
||||
|
||||
public static void handle(final LastInputTickPacket packet, final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
final NetworkEvent.Context context = contextSupplier.get();
|
||||
context.enqueueWork(() -> {
|
||||
// Get sender
|
||||
ServerPlayer sender = context.getSender();
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get protected player
|
||||
ProtectedPlayer protectedPlayer = ProtectedPlayerManager.getPlayer(sender.getUUID());
|
||||
if (protectedPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if player is afk
|
||||
if (sender.tickCount - packet.lastInputTick >= Config.Server.AFK_TIME_THRESHOLD.get() * 20) {
|
||||
ProtectedPlayerManager.updateState(sender.getUUID()); // Update state
|
||||
} else {
|
||||
ProtectedPlayerManager.startAfkTimer(sender.getUUID(), (long) ((Config.Server.AFK_TIME_THRESHOLD.get() -
|
||||
((sender.tickCount - packet.lastInputTick) / 20.0)) * 1000)); // Start new afk timer
|
||||
}
|
||||
});
|
||||
context.setPacketHandled(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package dev.micle.loginprotection.network.server;
|
||||
|
||||
import dev.micle.loginprotection.data.ProtectedPlayer;
|
||||
import dev.micle.loginprotection.proxy.Proxy;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PlayerStatePacket {
|
||||
private final ProtectedPlayer.State state;
|
||||
|
||||
public PlayerStatePacket(ProtectedPlayer.State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public static void encode(final PlayerStatePacket packet, final FriendlyByteBuf buffer) {
|
||||
buffer.writeUtf(packet.state.toString());
|
||||
}
|
||||
|
||||
public static PlayerStatePacket decode(final FriendlyByteBuf buffer) {
|
||||
return new PlayerStatePacket(ProtectedPlayer.State.valueOf(buffer.readUtf()));
|
||||
}
|
||||
|
||||
public static void handle(final PlayerStatePacket packet, final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
final NetworkEvent.Context context = contextSupplier.get();
|
||||
context.enqueueWork(() -> {
|
||||
Proxy.Client.setPlayerState(packet.state);
|
||||
});
|
||||
context.setPacketHandled(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package dev.micle.loginprotection.network.server;
|
||||
|
||||
import dev.micle.loginprotection.events.client.OnClientInputEventHandler;
|
||||
import dev.micle.loginprotection.network.NetworkManager;
|
||||
import dev.micle.loginprotection.network.client.LastInputTickPacket;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class RequestLastInputTickPacket {
|
||||
public static void encode(final RequestLastInputTickPacket packet, final FriendlyByteBuf buffer) {
|
||||
}
|
||||
|
||||
public static RequestLastInputTickPacket decode(final FriendlyByteBuf buffer) {
|
||||
return new RequestLastInputTickPacket();
|
||||
}
|
||||
|
||||
public static void handle(final RequestLastInputTickPacket packet, final Supplier<NetworkEvent.Context> contextSupplier) {
|
||||
final NetworkEvent.Context context = contextSupplier.get();
|
||||
context.enqueueWork(() -> {
|
||||
// Update last input tick (This works around GLFW forgetting about a repeat key after another one is pressed)
|
||||
OnClientInputEventHandler.checkIfInputIsAllowed();
|
||||
|
||||
// Send last input tick packet back to server
|
||||
NetworkManager.getChannel().sendToServer(new LastInputTickPacket());
|
||||
});
|
||||
context.setPacketHandled(true);
|
||||
}
|
||||
}
|
11
src/main/java/dev/micle/loginprotection/proxy/IProxy.java
Normal file
11
src/main/java/dev/micle/loginprotection/proxy/IProxy.java
Normal file
@ -0,0 +1,11 @@
|
||||
package dev.micle.loginprotection.proxy;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public interface IProxy {
|
||||
MinecraftServer getServer();
|
||||
Player getClientPlayer();
|
||||
Level getClientWorld();
|
||||
}
|
145
src/main/java/dev/micle/loginprotection/proxy/Proxy.java
Normal file
145
src/main/java/dev/micle/loginprotection/proxy/Proxy.java
Normal file
@ -0,0 +1,145 @@
|
||||
package dev.micle.loginprotection.proxy;
|
||||
|
||||
import dev.micle.loginprotection.LoginProtection;
|
||||
import dev.micle.loginprotection.data.ProtectedPlayer;
|
||||
import dev.micle.loginprotection.data.ProtectedPlayerManager;
|
||||
import dev.micle.loginprotection.events.client.OnClientInputEventHandler;
|
||||
import dev.micle.loginprotection.events.common.OnLivingSetAttackTargetEventHandler;
|
||||
import dev.micle.loginprotection.events.common.OnPlayerDamageEventHandler;
|
||||
import dev.micle.loginprotection.events.common.OnPlayerJoinEventHandler;
|
||||
import dev.micle.loginprotection.events.common.OnPlayerLeaveEventHandler;
|
||||
import dev.micle.loginprotection.network.NetworkManager;
|
||||
import dev.micle.loginprotection.setup.Config;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.AddReloadListenerEvent;
|
||||
import net.minecraftforge.event.server.ServerStartedEvent;
|
||||
import net.minecraftforge.event.server.ServerStoppingEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.event.lifecycle.*;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
|
||||
public class Proxy implements IProxy {
|
||||
// Initialize variables
|
||||
private static MinecraftServer server = null;
|
||||
|
||||
// Common setup
|
||||
public Proxy() {
|
||||
// Initialize setup
|
||||
Config.init();
|
||||
NetworkManager.init();
|
||||
|
||||
// Register mod event bus listeners
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
modEventBus.addListener(Proxy::setup);
|
||||
modEventBus.addListener(Proxy::imcEnqueue);
|
||||
modEventBus.addListener(Proxy::imcProcess);
|
||||
|
||||
// Register event but listeners
|
||||
MinecraftForge.EVENT_BUS.addListener(Proxy::onAddReloadListeners);
|
||||
MinecraftForge.EVENT_BUS.addListener(Proxy::serverStarted);
|
||||
MinecraftForge.EVENT_BUS.addListener(Proxy::serverStopping);
|
||||
|
||||
// Register event handlers
|
||||
MinecraftForge.EVENT_BUS.register(new OnLivingSetAttackTargetEventHandler());
|
||||
MinecraftForge.EVENT_BUS.register(new OnPlayerDamageEventHandler());
|
||||
MinecraftForge.EVENT_BUS.register(new OnPlayerJoinEventHandler());
|
||||
MinecraftForge.EVENT_BUS.register(new OnPlayerLeaveEventHandler());
|
||||
}
|
||||
|
||||
private static void setup(FMLCommonSetupEvent event) {}
|
||||
|
||||
private static void imcEnqueue(InterModEnqueueEvent event) {}
|
||||
|
||||
private static void imcProcess(InterModProcessEvent event) {}
|
||||
|
||||
private static void onAddReloadListeners(AddReloadListenerEvent event) {}
|
||||
|
||||
private static void serverStarted(ServerStartedEvent event) {
|
||||
ProtectedPlayerManager.init();
|
||||
server = event.getServer();
|
||||
}
|
||||
|
||||
private static void serverStopping(ServerStoppingEvent event) {
|
||||
server = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinecraftServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getClientPlayer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Level getClientWorld() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Client setup
|
||||
public static class Client extends Proxy {
|
||||
private static ProtectedPlayer.State playerState;
|
||||
private static int lastInputTick;
|
||||
|
||||
public Client() {
|
||||
// Register mod event bus listeners
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
modEventBus.addListener(Client::setup);
|
||||
modEventBus.addListener(Client::postSetup);
|
||||
|
||||
// Register event handlers
|
||||
MinecraftForge.EVENT_BUS.register(new OnClientInputEventHandler());
|
||||
}
|
||||
|
||||
private static void setup(FMLClientSetupEvent event) {}
|
||||
|
||||
private static void postSetup(FMLLoadCompleteEvent event) {}
|
||||
|
||||
public static ProtectedPlayer.State getPlayerState() {
|
||||
return playerState;
|
||||
}
|
||||
|
||||
public static void setPlayerState(ProtectedPlayer.State newPlayerState) {
|
||||
playerState = newPlayerState;
|
||||
}
|
||||
|
||||
public static int getLastInputTick() {
|
||||
return lastInputTick;
|
||||
}
|
||||
|
||||
public static void updateLastInputTick() {
|
||||
lastInputTick = LoginProtection.getProxy().getClientPlayer().tickCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public Player getClientPlayer() {
|
||||
return Minecraft.getInstance().player;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public Level getClientWorld() {
|
||||
return Minecraft.getInstance().level;
|
||||
}
|
||||
}
|
||||
|
||||
// Server setup
|
||||
public static class Server extends Proxy {
|
||||
public Server() {
|
||||
// Register mod event bus listeners
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
modEventBus.addListener(Server::setup);
|
||||
}
|
||||
|
||||
private static void setup(FMLDedicatedServerSetupEvent event) {}
|
||||
}
|
||||
}
|
174
src/main/java/dev/micle/loginprotection/setup/Config.java
Normal file
174
src/main/java/dev/micle/loginprotection/setup/Config.java
Normal file
@ -0,0 +1,174 @@
|
||||
package dev.micle.loginprotection.setup;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import dev.micle.loginprotection.LoginProtection;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = LoginProtection.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public final class Config {
|
||||
public static final Server SERVER;
|
||||
public static final ForgeConfigSpec SERVER_SPEC;
|
||||
static {
|
||||
Pair<Server, ForgeConfigSpec> spec_pair = new ForgeConfigSpec.Builder().configure(Server::new);
|
||||
SERVER = spec_pair.getLeft();
|
||||
SERVER_SPEC = spec_pair.getRight();
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, SERVER_SPEC);
|
||||
}
|
||||
|
||||
public static class Server {
|
||||
public static ForgeConfigSpec.BooleanValue POST_REFILL_AIR_ENABLED;
|
||||
public static ForgeConfigSpec.BooleanValue POST_WATER_ENABLED;
|
||||
public static ForgeConfigSpec.IntValue POST_WATER_DURATION;
|
||||
public static ForgeConfigSpec.BooleanValue POST_LAVA_ENABLED;
|
||||
public static ForgeConfigSpec.IntValue POST_LAVA_DURATION;
|
||||
public static ForgeConfigSpec.BooleanValue POST_FIRE_ENABLED;
|
||||
public static ForgeConfigSpec.IntValue POST_FIRE_DURATION;
|
||||
|
||||
public static ForgeConfigSpec.BooleanValue LOGIN_MOBS_IGNORE_PLAYER;
|
||||
public static ForgeConfigSpec.BooleanValue LOGIN_APPLY_POST_EFFECTS;
|
||||
public static ForgeConfigSpec.ConfigValue<List<? extends String>> LOGIN_KEY_ALLOW_LIST;
|
||||
public static ForgeConfigSpec.BooleanValue LOGIN_GRACE_ENABLED;
|
||||
public static ForgeConfigSpec.BooleanValue LOGIN_GRACE_MOBS_IGNORE_PLAYER;
|
||||
public static ForgeConfigSpec.IntValue LOGIN_GRACE_DURATION;
|
||||
|
||||
public static ForgeConfigSpec.BooleanValue AFK_PROTECTION_ENABLED;
|
||||
public static ForgeConfigSpec.IntValue AFK_TIME_THRESHOLD;
|
||||
public static ForgeConfigSpec.BooleanValue AFK_APPLY_POST_EFFECTS;
|
||||
public static ForgeConfigSpec.BooleanValue AFK_MOBS_IGNORE_PLAYER;
|
||||
public static ForgeConfigSpec.ConfigValue<List<? extends String>> AFK_KEY_ALLOW_LIST;
|
||||
public static ForgeConfigSpec.BooleanValue AFK_GRACE_ENABLED;
|
||||
public static ForgeConfigSpec.BooleanValue AFK_GRACE_MOBS_IGNORE_PLAYER;
|
||||
public static ForgeConfigSpec.IntValue AFK_GRACE_DURATION;
|
||||
|
||||
Server(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment("Settings for protecting players while they are joining.").push("Login");
|
||||
LOGIN_APPLY_POST_EFFECTS = builder
|
||||
.comment("Whether to apply any post protection effects to joining players.")
|
||||
.define("applyPostProtectionEffects", true);
|
||||
LOGIN_MOBS_IGNORE_PLAYER = builder
|
||||
.comment("Whether mobs will ignore a protected player. (They will not attack/aggro)")
|
||||
.define("mobsIgnorePlayer", true);
|
||||
builder.push("AllowedKeys");
|
||||
LOGIN_KEY_ALLOW_LIST = builder
|
||||
.comment("Allowed keys players can press without becoming active.\n" +
|
||||
"Available values: PAUSE, DEBUG, FULLSCREEN, PERSPECTIVE, SMOOTH_CAMERA, SCREENSHOT, SPECTATOR_OUTLINES,\n" +
|
||||
"ADVANCEMENTS, PLAYER_LIST, CHAT, SOCIAL_INTERACTIONS, LOAD_HOTBAR_ACTIVATOR, SAVE_HOTBAR_ACTIVATOR,\n" +
|
||||
"SWAP_ITEM, INVENTORY, HOTBAR, DROP_ITEM, USE_ITEM, PICK_BLOCK, ATTACK, MOVE, SNEAK, JUMP")
|
||||
.defineList("allowedKeys", Lists.newArrayList(KEYS.PAUSE.toString(), KEYS.DEBUG.toString(), KEYS.FULLSCREEN.toString(), KEYS.PERSPECTIVE.toString(), KEYS.SMOOTH_CAMERA.toString(),
|
||||
KEYS.SCREENSHOT.toString(), KEYS.SPECTATOR_OUTLINES.toString(), KEYS.ADVANCEMENTS.toString(), KEYS.PLAYER_LIST.toString(), KEYS.CHAT.toString(), KEYS.SOCIAL_INTERACTIONS.toString(),
|
||||
KEYS.LOAD_HOTBAR_ACTIVATOR.toString(), KEYS.SAVE_HOTBAR_ACTIVATOR.toString(), KEYS.SWAP_ITEM.toString(), KEYS.HOTBAR.toString(), KEYS.PICK_BLOCK.toString()), o -> o instanceof String);
|
||||
builder.pop();
|
||||
builder.push("Grace");
|
||||
LOGIN_GRACE_ENABLED = builder
|
||||
.comment("Whether a player receives a grace period after becoming active or not.")
|
||||
.define("graceEnabled", true);
|
||||
LOGIN_GRACE_MOBS_IGNORE_PLAYER = builder
|
||||
.comment("Whether mobs ignore the player during their grace period.")
|
||||
.define("graceMobsIgnorePlayer", true);
|
||||
LOGIN_GRACE_DURATION = builder
|
||||
.comment("How long the grace period lasts in seconds.")
|
||||
.defineInRange("graceDuration", 10, 1, Integer.MAX_VALUE);
|
||||
builder.pop();
|
||||
builder.pop();
|
||||
|
||||
builder.comment("Settings for protecting players that are afk.").push("AFK");
|
||||
AFK_PROTECTION_ENABLED = builder
|
||||
.comment("Enable protection of afk players?")
|
||||
.define("enabled", true);
|
||||
AFK_TIME_THRESHOLD = builder
|
||||
.comment("How long a player needs to be afk to become protected. (seconds)")
|
||||
.defineInRange("timeThreshold", 600, 1, Integer.MAX_VALUE/20);
|
||||
AFK_APPLY_POST_EFFECTS = builder
|
||||
.comment("Whether to apply any post protection effects to afk players.")
|
||||
.define("applyPostProtectionEffects", false);
|
||||
AFK_MOBS_IGNORE_PLAYER = builder
|
||||
.comment("Whether mobs will ignore a protected player. (They will not attack/aggro")
|
||||
.define("mobsIgnorePlayerEnabled", true);
|
||||
builder.push("AllowedKeys");
|
||||
AFK_KEY_ALLOW_LIST = builder
|
||||
.comment("Allowed keys players can press without becoming active.\n" +
|
||||
"Available values: PAUSE, DEBUG, FULLSCREEN, PERSPECTIVE, SMOOTH_CAMERA, SCREENSHOT, SPECTATOR_OUTLINES,\n" +
|
||||
"ADVANCEMENTS, PLAYER_LIST, CHAT, SOCIAL_INTERACTIONS, LOAD_HOTBAR_ACTIVATOR, SAVE_HOTBAR_ACTIVATOR,\n" +
|
||||
"SWAP_ITEM, INVENTORY, HOTBAR, DROP_ITEM, USE_ITEM, PICK_BLOCK, ATTACK, MOVE, SNEAK, JUMP")
|
||||
.defineList("allowedKeys", Lists.newArrayList(KEYS.PAUSE.toString(), KEYS.FULLSCREEN.toString(), KEYS.SCREENSHOT.toString(), KEYS.ADVANCEMENTS.toString()), o -> o instanceof String);
|
||||
builder.pop();
|
||||
builder.push("Grace");
|
||||
AFK_GRACE_ENABLED = builder
|
||||
.comment("Whether a player receives a grace period after becoming active or not.")
|
||||
.define("graceEnabled", false);
|
||||
AFK_GRACE_MOBS_IGNORE_PLAYER = builder
|
||||
.comment("Whether mobs ignore the player during their grace period.")
|
||||
.define("graceMobsIgnorePlayer", true);
|
||||
AFK_GRACE_DURATION = builder
|
||||
.comment("How long the grace period lasts in seconds.")
|
||||
.defineInRange("graceDuration", 5, 1, Integer.MAX_VALUE);
|
||||
builder.pop();
|
||||
builder.pop();
|
||||
|
||||
builder.comment("Additional protection settings that apply as soon as a player becomes active if enabled.").push("Post");
|
||||
builder.push("WaterProtection");
|
||||
POST_REFILL_AIR_ENABLED = builder
|
||||
.comment("Whether a player's air supply gets refilled.")
|
||||
.define("refillAir", true);
|
||||
POST_WATER_ENABLED = builder
|
||||
.comment("Whether a player receives water breathing when in water.")
|
||||
.define("waterEnabled", false);
|
||||
POST_WATER_DURATION = builder
|
||||
.comment("Water breathing duration in seconds.")
|
||||
.defineInRange("waterDuration", 10, 1, Integer.MAX_VALUE/20);
|
||||
builder.pop();
|
||||
builder.push("LavaProtection");
|
||||
POST_LAVA_ENABLED = builder
|
||||
.comment("Whether a player receives fire resistance when in lava.")
|
||||
.define("enabled", true);
|
||||
POST_LAVA_DURATION = builder
|
||||
.comment("Fire resistance duration in seconds.")
|
||||
.defineInRange("duration", 10, 1, Integer.MAX_VALUE/20);
|
||||
builder.pop();
|
||||
builder.push("FireProtection");
|
||||
POST_FIRE_ENABLED = builder
|
||||
.comment("Whether a player receives fire resistance when on fire.")
|
||||
.define("enabled", false);
|
||||
POST_FIRE_DURATION = builder
|
||||
.comment("Fire resistance duration in seconds.")
|
||||
.defineInRange("duration", 10, 1, Integer.MAX_VALUE/20);
|
||||
builder.pop();
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
public enum KEYS {
|
||||
PAUSE,
|
||||
DEBUG,
|
||||
FULLSCREEN,
|
||||
PERSPECTIVE,
|
||||
SMOOTH_CAMERA,
|
||||
SCREENSHOT,
|
||||
SPECTATOR_OUTLINES,
|
||||
ADVANCEMENTS,
|
||||
PLAYER_LIST,
|
||||
CHAT,
|
||||
SOCIAL_INTERACTIONS,
|
||||
LOAD_HOTBAR_ACTIVATOR,
|
||||
SAVE_HOTBAR_ACTIVATOR,
|
||||
SWAP_ITEM,
|
||||
INVENTORY,
|
||||
HOTBAR,
|
||||
DROP_ITEM,
|
||||
USE_ITEM,
|
||||
PICK_BLOCK,
|
||||
ATTACK,
|
||||
MOVE,
|
||||
SNEAK,
|
||||
JUMP
|
||||
}
|
||||
}
|
||||
}
|
58
src/main/resources/META-INF/mods.toml
Normal file
58
src/main/resources/META-INF/mods.toml
Normal file
@ -0,0 +1,58 @@
|
||||
# This is an example mods.toml file. It contains the data relating to the loading mods.
|
||||
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
|
||||
# The overall format is standard TOML format, v0.5.0.
|
||||
# Note that there are a couple of TOML lists in this file.
|
||||
# Find more information on toml format here: https://github.com/toml-lang/toml
|
||||
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
|
||||
modLoader = "javafml" #mandatory
|
||||
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
|
||||
loaderVersion = "[40,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
|
||||
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
|
||||
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
|
||||
license = "All Rights Reserved"
|
||||
# A URL to refer people to when problems occur with this mod
|
||||
#issueTrackerURL="http://my.issue.tracker/" #optional
|
||||
# A list of mods - how many allowed here is determined by the individual mod loader
|
||||
[[mods]] #mandatory
|
||||
# The modid of the mod
|
||||
modId = "loginprotection" #mandatory
|
||||
# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
|
||||
# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
|
||||
# see the associated build.gradle script for how to populate this completely automatically during a build
|
||||
version = "${file.jarVersion}" #mandatory
|
||||
# A display name for the mod
|
||||
displayName = "Micle's Login Protection" #mandatory
|
||||
# A URL to query for updates for this mod. See the JSON update specification <here>
|
||||
#updateJSONURL="http://myurl.me/" #optional
|
||||
# A URL for the "homepage" for this mod, displayed in the mod UI
|
||||
#displayURL="http://example.com/" #optional
|
||||
# A file name (in the root of the mod JAR) containing a logo for display
|
||||
logoFile="logo.jpg" #optional
|
||||
# A text field displayed in the mod UI
|
||||
#credits="Thanks for this example mod goes to Java" #optional
|
||||
# A text field displayed in the mod UI
|
||||
authors = "Micle" #optional
|
||||
# The description text for the mod (multi line!) (#mandatory)
|
||||
description = '''
|
||||
Protects players from damage while they are are joining a server or are AFK.
|
||||
'''
|
||||
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
|
||||
[[dependencies.loginprotection]] #optional
|
||||
# the modid of the dependency
|
||||
modId = "forge" #mandatory
|
||||
# Does this dependency have to exist - if not, ordering below must be specified
|
||||
mandatory = true #mandatory
|
||||
# The version range of the dependency
|
||||
versionRange = "[40,)" #mandatory
|
||||
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
|
||||
ordering = "NONE"
|
||||
# Side this dependency is applied on - BOTH, CLIENT or SERVER
|
||||
side = "BOTH"
|
||||
# Here's another dependency
|
||||
[[dependencies.loginprotection]]
|
||||
modId = "minecraft"
|
||||
mandatory = true
|
||||
# This version range declares a minimum of the current minecraft version up to but not including the next major version
|
||||
versionRange = "[1.18.2,1.19)"
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
15
src/main/resources/loginprotection.mixins.json
Normal file
15
src/main/resources/loginprotection.mixins.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "dev.micle.loginprotection.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"refmap": "loginprotection.refmap.json",
|
||||
"mixins": [
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"client": [
|
||||
"GuiRenderTickMixin"
|
||||
]
|
||||
}
|
BIN
src/main/resources/logo.jpg
(Stored with Git LFS)
Normal file
BIN
src/main/resources/logo.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
6
src/main/resources/pack.mcmeta
Normal file
6
src/main/resources/pack.mcmeta
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "loginprotection resources",
|
||||
"pack_format": 8
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user