Compare commits

..

6 Commits

Author SHA1 Message Date
c4aed126d8
chore: update to 1.21.3
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-10-23 21:37:19 +02:00
fa5aa9edf9
chore: update to 1.21
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-06-14 14:21:37 +02:00
de00f51b06
fix: build in gradle:latest
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-04-25 22:21:50 +02:00
3fa30b834d
chore: update to 1.20.5
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/tag/woodpecker Pipeline failed
2024-04-25 21:51:15 +02:00
0e036599cf
fix: don't respond to events for other players if on client
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-03-31 14:13:42 +02:00
3b5e262bea
fix: hook additional methods for a better chance to catch damage
Some checks are pending
ci/woodpecker/tag/woodpecker Pipeline is pending
ci/woodpecker/push/woodpecker Pipeline was successful
2024-03-31 13:58:58 +02:00
12 changed files with 120 additions and 47 deletions

View File

@ -2,7 +2,7 @@
steps: steps:
build_test: build_test:
image: gradle:alpine image: gradle:latest
pull: true pull: true
commands: commands:
- mkdir artifacts - mkdir artifacts

View File

@ -8,19 +8,19 @@ import java.util.function.Supplier
import javax.lang.model.element.Modifier.* import javax.lang.model.element.Modifier.*
plugins { plugins {
id("jfmod") version "1.5-SNAPSHOT" id("jfmod") version "1.6-SNAPSHOT"
} }
allprojects { group = "io.gitlab.jfronny" } allprojects { group = "io.gitlab.jfronny" }
base.archivesName = "breakme" base.archivesName = "breakme"
// https://fabricmc.net/develop/ // https://fabricmc.net/develop/
val fabricVersion = "0.91.1+1.20.4"
jfMod { jfMod {
minecraftVersion = "1.20.4" minecraftVersion = "1.21.3"
yarn("build.1") yarn("build.2")
loaderVersion = "0.15.0" loaderVersion = "0.16.7"
libJfVersion = "3.14.1" libJfVersion = "3.18.0"
fabricApiVersion = "0.106.1+1.21.3"
modrinth { modrinth {
projectId = "breakme" projectId = "breakme"
@ -37,13 +37,13 @@ jfMod {
if (flavour == "") flavour = "modrinth" if (flavour == "") flavour = "modrinth"
dependencies { dependencies {
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v2:${jfMod.libJfVersion.get()}") modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v2")
// Dev env // Dev env
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:${jfMod.libJfVersion.get()}") modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil")
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny:${jfMod.libJfVersion.get()}") modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny")
modLocalRuntime("net.fabricmc.fabric-api:fabric-api:$fabricVersion") modLocalRuntime("net.fabricmc.fabric-api:fabric-api")
modLocalRuntime("com.terraformersmc:modmenu:9.0.0-pre.1") modLocalRuntime("com.terraformersmc:modmenu:12.0.0-beta.1")
} }
loom { loom {
@ -52,7 +52,7 @@ loom {
} }
} }
fun list(`package`: String) = Files.list(projectDir.resolve("src/main/java").resolve(`package`.replace('.', '/')).toPath()).use { stream -> fun list(`package`: String): List<ClassName> = Files.list(projectDir.resolve("src/main/java").resolve(`package`.replace('.', '/')).toPath()).use { stream ->
stream stream
.map { it.fileName.toString() } .map { it.fileName.toString() }
.map { it.substring(0, it.lastIndexOf('.')) } .map { it.substring(0, it.lastIndexOf('.')) }

View File

@ -1,7 +1,6 @@
pluginManagement { pluginManagement {
repositories { repositories {
maven("https://maven.fabricmc.net/") // FabricMC maven("https://maven.frohnmeyer-wds.de/mirrors")
maven("https://maven.frohnmeyer-wds.de/artifacts") // scripts
gradlePluginPortal() gradlePluginPortal()
} }
} }

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.breakme.client; package io.gitlab.jfronny.breakme.client;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.thread.ThreadExecutor; import net.minecraft.util.thread.ThreadExecutor;
import java.util.Objects; import java.util.Objects;
@ -10,4 +11,11 @@ public class ClientImpl implements Client {
public ThreadExecutor<Runnable> getRunner() { public ThreadExecutor<Runnable> getRunner() {
return Objects.requireNonNull(MinecraftClient.getInstance()); return Objects.requireNonNull(MinecraftClient.getInstance());
} }
@Override
public boolean isValidPlayer(PlayerEntity player) {
MinecraftClient client = MinecraftClient.getInstance();
if (client == null || client.player == null) return false;
return client.player.getUuid().equals(player.getUuid());
}
} }

View File

@ -1,28 +1,47 @@
package io.gitlab.jfronny.breakme; package io.gitlab.jfronny.breakme;
import io.gitlab.jfronny.breakme.client.Client;
import io.gitlab.jfronny.breakme.crash.Method; import io.gitlab.jfronny.breakme.crash.Method;
import io.gitlab.jfronny.commons.logging.Logger; import io.gitlab.jfronny.commons.logger.SystemLoggerPlus;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Language; import net.minecraft.util.Language;
public class BreakMe implements ModInitializer { public class BreakMe implements ModInitializer {
public static final String MOD_ID = "breakme"; public static final String MOD_ID = "breakme";
public static final Logger LOGGER = Logger.forName(MOD_ID); public static final SystemLoggerPlus LOGGER = SystemLoggerPlus.forName(MOD_ID);
@Override @Override
public void onInitialize() { public void onInitialize() {
LOGGER.warn("Prepare for trouble"); LOGGER.warn("Prepare for trouble");
} }
public static void tryInvokeCrash(PlayerEntity player) throws Exception { public static void tryInvokeCrash(BreakMeConfig.Cause cause) throws Exception {
if (BreakMeConfig.event == BreakMeConfig.Cause.All if (BreakMeConfig.event.includes(cause)) {
|| BreakMeConfig.event == BreakMeConfig.Cause.Damage crash();
|| (BreakMeConfig.event == BreakMeConfig.Cause.Death && player.isDead())) {
Method method = BreakMeConfig.method;
String name = Language.getInstance().get(MOD_ID + ".jfconfig.enum.Method." + method.name(), method.name());
LOGGER.info("Invoking the crash (using " + name + ")");
method.crash();
} }
} }
public static BreakMeConfig.Cause resolveEvent(PlayerEntity player) {
if (!isValidPlayer(player)) return BreakMeConfig.Cause.None;
else if (player.isDead()) return BreakMeConfig.Cause.Death;
else return BreakMeConfig.Cause.Damage;
}
public static boolean isValidPlayer(PlayerEntity player) {
if (player == null) return false;
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
return Client.INSTANCE.isValidPlayer(player);
}
return true;
}
private static void crash() throws Exception {
Method method = BreakMeConfig.method;
String name = Language.getInstance().get(MOD_ID + ".jfconfig.enum.Method." + method.name(), method.name());
LOGGER.info("Invoking the crash (using {0})", name);
method.crash();
}
} }

View File

@ -13,7 +13,12 @@ public class BreakMeConfig {
Death, Death,
All, All,
None None;
public boolean includes(Cause cause) {
if (cause == null || cause == None) return false;
return this == All || this == cause;
}
} }
@Verifier @Verifier
@ -24,6 +29,14 @@ public class BreakMeConfig {
} }
} }
@Verifier
public static void validEvent() {
if (BreakMeConfig.event == null) {
BreakMeConfig.event = Cause.None;
BreakMe.LOGGER.error("Could not find specified event, defaulting to None");
}
}
static { static {
JFC_BreakMeConfig.ensureInitialized(); JFC_BreakMeConfig.ensureInitialized();
} }

View File

@ -1,10 +1,12 @@
package io.gitlab.jfronny.breakme.client; package io.gitlab.jfronny.breakme.client;
import io.gitlab.jfronny.commons.throwable.Try; import io.gitlab.jfronny.commons.throwable.Try;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.thread.ThreadExecutor; import net.minecraft.util.thread.ThreadExecutor;
public interface Client { public interface Client {
Client INSTANCE = (Client) Try.orThrow(() -> Class.forName(Client.class.getName() + "Impl").getConstructor().newInstance()); Client INSTANCE = (Client) Try.orThrow(() -> Class.forName(Client.class.getName() + "Impl").getConstructor().newInstance());
ThreadExecutor<Runnable> getRunner(); ThreadExecutor<Runnable> getRunner();
boolean isValidPlayer(PlayerEntity player);
} }

View File

@ -13,7 +13,7 @@ public class SegfaultProvider implements CrashProvider {
// Required to prevent early initialization of LWJGL for some reason // Required to prevent early initialization of LWJGL for some reason
private static class Impl { private static class Impl {
private static void crash() { private static void crash() {
BufferUtils.zeroBuffer(PointerBuffer.create(0, 1000)); BufferUtils.zeroBuffer(PointerBuffer.create(1, 1000));
} }
} }
} }

View File

@ -0,0 +1,21 @@
package io.gitlab.jfronny.breakme.mixin;
import io.gitlab.jfronny.breakme.BreakMe;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
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(LivingEntity.class)
public class LivingEntityMixin {
// client-side damage event when playing on a server
@Inject(at = @At("TAIL"), method = "onDamaged(Lnet/minecraft/entity/damage/DamageSource;)V")
private void onDamage(DamageSource damageSource, CallbackInfo ci) throws Exception {
if (((LivingEntity)(Object)this) instanceof PlayerEntity player) {
BreakMe.tryInvokeCrash(BreakMe.resolveEvent(player));
}
}
}

View File

@ -1,19 +0,0 @@
package io.gitlab.jfronny.breakme.mixin;
import io.gitlab.jfronny.breakme.BreakMe;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
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;
@Mixin(PlayerEntity.class)
public class MixinPlayerEntity {
@Inject(at = @At("TAIL"), method = "damage(Lnet/minecraft/entity/damage/DamageSource;F)Z")
private void onDamage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) throws Exception {
if (info.getReturnValue()) {
BreakMe.tryInvokeCrash((PlayerEntity)(Object)this);
}
}
}

View File

@ -0,0 +1,29 @@
package io.gitlab.jfronny.breakme.mixin;
import io.gitlab.jfronny.breakme.BreakMe;
import io.gitlab.jfronny.breakme.BreakMeConfig;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.world.ServerWorld;
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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PlayerEntity.class)
public class PlayerEntityMixin {
@Inject(at = @At("TAIL"), method = "damage(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/entity/damage/DamageSource;F)Z")
private void onDamage(ServerWorld world, DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) throws Exception {
if (cir.getReturnValue()) {
BreakMe.tryInvokeCrash(BreakMe.resolveEvent((PlayerEntity)(Object)this));
}
}
@Inject(at = @At("TAIL"), method = "onDeath(Lnet/minecraft/entity/damage/DamageSource;)V")
private void onDeath(DamageSource damageSource, CallbackInfo ci) throws Exception {
if (BreakMe.isValidPlayer((PlayerEntity)(Object)this)) {
BreakMe.tryInvokeCrash(BreakMeConfig.Cause.Death);
}
}
}

View File

@ -4,9 +4,10 @@
"package": "io.gitlab.jfronny.breakme.mixin", "package": "io.gitlab.jfronny.breakme.mixin",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_8",
"mixins": [ "mixins": [
"MixinPlayerEntity" "PlayerEntityMixin"
], ],
"client": [ "client": [
"LivingEntityMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1