Compare commits

..

No commits in common. "master" and "4.11.2" have entirely different histories.

12 changed files with 47 additions and 120 deletions

View File

@ -2,7 +2,7 @@
steps: steps:
build_test: build_test:
image: gradle:latest image: gradle:alpine
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.6-SNAPSHOT" id("jfmod") version "1.5-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.21.3" minecraftVersion = "1.20.4"
yarn("build.2") yarn("build.1")
loaderVersion = "0.16.7" loaderVersion = "0.15.0"
libJfVersion = "3.18.0" libJfVersion = "3.14.1"
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") modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v2:${jfMod.libJfVersion.get()}")
// Dev env // Dev env
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil") modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:${jfMod.libJfVersion.get()}")
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny") modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny:${jfMod.libJfVersion.get()}")
modLocalRuntime("net.fabricmc.fabric-api:fabric-api") modLocalRuntime("net.fabricmc.fabric-api:fabric-api:$fabricVersion")
modLocalRuntime("com.terraformersmc:modmenu:12.0.0-beta.1") modLocalRuntime("com.terraformersmc:modmenu:9.0.0-pre.1")
} }
loom { loom {
@ -52,7 +52,7 @@ loom {
} }
} }
fun list(`package`: String): List<ClassName> = Files.list(projectDir.resolve("src/main/java").resolve(`package`.replace('.', '/')).toPath()).use { stream -> fun list(`package`: String) = 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,6 +1,7 @@
pluginManagement { pluginManagement {
repositories { repositories {
maven("https://maven.frohnmeyer-wds.de/mirrors") maven("https://maven.fabricmc.net/") // FabricMC
maven("https://maven.frohnmeyer-wds.de/artifacts") // scripts
gradlePluginPortal() gradlePluginPortal()
} }
} }

View File

@ -1,7 +1,6 @@
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;
@ -11,11 +10,4 @@ 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,47 +1,28 @@
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.logger.SystemLoggerPlus; import io.gitlab.jfronny.commons.logging.Logger;
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 SystemLoggerPlus LOGGER = SystemLoggerPlus.forName(MOD_ID); public static final Logger LOGGER = Logger.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(BreakMeConfig.Cause cause) throws Exception { public static void tryInvokeCrash(PlayerEntity player) throws Exception {
if (BreakMeConfig.event.includes(cause)) { if (BreakMeConfig.event == BreakMeConfig.Cause.All
crash(); || BreakMeConfig.event == BreakMeConfig.Cause.Damage
|| (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,12 +13,7 @@ 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
@ -29,14 +24,6 @@ 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,12 +1,10 @@
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(1, 1000)); BufferUtils.zeroBuffer(PointerBuffer.create(0, 1000));
} }
} }
} }

View File

@ -1,21 +0,0 @@
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

@ -0,0 +1,19 @@
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

@ -1,29 +0,0 @@
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,10 +4,9 @@
"package": "io.gitlab.jfronny.breakme.mixin", "package": "io.gitlab.jfronny.breakme.mixin",
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_8",
"mixins": [ "mixins": [
"PlayerEntityMixin" "MixinPlayerEntity"
], ],
"client": [ "client": [
"LivingEntityMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1