Skip to content

Commit 9092151

Browse files
authored
Fix SME disarm (#5)
* Fix SME disarm * Some hacks * Cleanup & Version 0.1.0
1 parent d23732e commit 9092151

File tree

10 files changed

+143
-11
lines changed

10 files changed

+143
-11
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Provide bugfixes, optimizations and utilities for Forge+Bukkit server environmen
1818
- Fix Twilight Forest Chain with Block can break blocks in protected areas
1919
- Fix Thaumcraft 6 taint can spread into protected areas
2020
- Fix trait effects in Tinkers' Construct can bypass damage protection
21+
- Fix So Many Enchantments can disarm players in protected areas
2122

2223
## Features
2324

build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ dependencies {
137137
// Tinkers Construct
138138
compileOnly rfg.deobf("curse.maven:tinkers-construct-74072:2902483")
139139
compileOnly rfg.deobf("curse.maven:mantle-74924:2713386")
140+
141+
// So many enchantments
142+
compileOnly rfg.deobf("curse.maven:so-many-enchantments-267035:6172363")
140143
if (propertyBool('use_modern_java_syntax')) {
141144
annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0'
142145
// Workaround for https://github.com/bsideup/jabel/issues/174

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ generate_javadocs_jar = false
1111

1212
# Mod Information
1313
# HIGHLY RECOMMEND complying with SemVer for mod_version: https://semver.org/
14-
mod_version = 0.0.5
14+
mod_version = 0.1.0
1515
root_package = io.wdsj
1616
mod_id = hybridfix
1717
mod_name = HybridFix
@@ -101,7 +101,7 @@ mixin_booter_version = 10.5
101101
# You should change package root once they are generated
102102
generate_mixins_json = true
103103
# Delimit configs with spaces. Should only put configs name instead of full file name
104-
mixin_configs = fix.respawn tconstruct.tools thaumcraft.taint twilight_forest.item twilight_forest.entity twilight_forest.sapling bridge.duck bridge.explosion.mohist fix.respawn.mohist perf.eventbus perf.server perf.timings.v1 misc.command bukkit.plugin
104+
mixin_configs = fix.respawn so_many_enchantments.disarm tconstruct.tools thaumcraft.taint twilight_forest.item twilight_forest.entity twilight_forest.sapling bridge.duck bridge.explosion.mohist fix.respawn.mohist perf.eventbus perf.server perf.timings.v1 misc.command bukkit.plugin
105105
# A refmap is a json that denotes mapping conversions, this json is generated automatically, with the name `mixins.mod_id.refmap.json`
106106
# Use the property `mixin_refmap` if you want it to use a different name, only one name is accepted
107107
mixin_refmap = mixins.${mod_id}.refmap.json

src/main/java/io/wdsj/hybridfix/HybridFixLateLoader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ public class HybridFixLateLoader implements ILateMixinLoader {
2929
put("mixins.thaumcraft.taint.json", () -> isModLoaded("thaumcraft") && Settings.modPatchSettings.patchThaumcraftTaintSpread);
3030
// Tconstruct patches
3131
put("mixins.tconstruct.tools.json", () -> isModLoaded("tconstruct") && Settings.modPatchSettings.patchTconstructToolDamage);
32+
// So Many Enchantments patches
33+
put("mixins.so_many_enchantments.disarm.json", () -> isModLoaded("somanyenchantments") && Settings.modPatchSettings.patchSoManyEnchantmentsDisarm);
3234
}
3335
});
3436

src/main/java/io/wdsj/hybridfix/HybridFixServer.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
import net.minecraftforge.common.MinecraftForge;
1111
import net.minecraftforge.server.permission.PermissionAPI;
1212
import org.bukkit.Bukkit;
13-
import org.bukkit.craftbukkit.v1_12_R1.CraftCrashReport;
14-
15-
import java.util.logging.Level;
1613

1714
import static io.wdsj.hybridfix.HybridFix.HAS_CLEANROOM;
1815

src/main/java/io/wdsj/hybridfix/config/Settings.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ public static class ModPatchSettings {
7979
@Config.Comment("Patch Tinkers Construct tool damage,\nUseful for some traits that adds extra effects and disarming, etc.\nYou can use property -Dhybridfix.tconstruct.supersedeVanillaEvent=true to prevent calling original damage event.")
8080
@Config.RequiresMcRestart
8181
public boolean patchTconstructToolDamage = false;
82+
83+
@Config.Comment("Patch Disarm enchantment in SME(1.0.0 and higher), prevent bypassing the bukkit protection.")
84+
@Config.RequiresMcRestart
85+
public boolean patchSoManyEnchantmentsDisarm = false;
8286
}
8387
@Config.Comment("Configuration for HybridFix built-in bukkit plugin.")
8488
@Config.RequiresMcRestart

src/main/java/io/wdsj/hybridfix/entry/bukkit/util/ListenerUtils.java renamed to src/main/java/io/wdsj/hybridfix/entry/bukkit/util/ListenerHackery.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,19 @@
1010
import java.io.InputStream;
1111
import java.lang.reflect.Method;
1212

13-
public class ListenerUtils {
14-
private ListenerUtils() {
13+
public class ListenerHackery {
14+
private ListenerHackery() {
1515
}
1616

17+
/*
18+
private static final boolean disableModuleSystemHack = Boolean.getBoolean("hybridfix.disableModuleSystemHack");
19+
static {
20+
if (getJavaMajorVersion() >= 17 && !disableModuleSystemHack) {
21+
HybridFix.LOGGER.info("Java version is 17+, attempting to hack into module system.");
22+
hackModuleSystem();
23+
}
24+
}
25+
*/
1726
/**
1827
* Hack to register a listener to target plugin ClassLoader that bypasses the isolation.
1928
* @param clazz listener class
@@ -42,4 +51,35 @@ public static void registerListenerToTargetPlugin(Class<? extends Listener> claz
4251
SneakyThrow.sneaky(e);
4352
}
4453
}
54+
55+
/*
56+
private static void hackModuleSystem() {
57+
try {
58+
Class<?> UnsafeClass = Class.forName("sun.misc.Unsafe");
59+
Field unsafeField = UnsafeClass.getDeclaredField("theUnsafe");
60+
unsafeField.setAccessible(true);
61+
Unsafe unsafe = (Unsafe) unsafeField.get(null);
62+
Method getModule = Class.class.getMethod("getModule");
63+
Object objectModule = getModule.invoke(Object.class);
64+
65+
long addr = unsafe.objectFieldOffset(Class.class.getDeclaredField("module"));
66+
unsafe.getAndSetObject(ListenerHackery.class, addr, objectModule);
67+
} catch (Throwable e) {
68+
HybridFix.LOGGER.warn("Failed to hack into module system, you may need to manually add --add-opens=java.base/java.lang=ALL-UNNAMED to your startup flags to make plugin hooks work properly.", e);
69+
}
70+
}
71+
72+
private static int getJavaMajorVersion() {
73+
String version = System.getProperty("java.version");
74+
if (version.startsWith("1.")) {
75+
return version.charAt(2) - '0';
76+
}
77+
if (version.contains("-")) {
78+
version = version.substring(0, version.indexOf("-"));
79+
}
80+
81+
int dotIndex = version.indexOf(".");
82+
return Integer.parseInt(dotIndex == -1 ? version : version.substring(0, dotIndex));
83+
}
84+
*/
4585
}

src/main/java/io/wdsj/hybridfix/mixin/bukkit/plugin/DedicatedServerMixin.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import io.wdsj.hybridfix.entry.bukkit.hook.worldguard.WGHookEntityChangeBlockListener;
88
import io.wdsj.hybridfix.entry.bukkit.listener.ExplodeListener;
99
import io.wdsj.hybridfix.entry.bukkit.hook.residence.ResHookEntityChangeBlockListener;
10-
import io.wdsj.hybridfix.entry.bukkit.util.ListenerUtils;
10+
import io.wdsj.hybridfix.entry.bukkit.util.ListenerHackery;
1111
import net.minecraft.server.dedicated.DedicatedServer;
1212
import org.bukkit.Bukkit;
1313
import org.bukkit.ChatColor;
@@ -41,8 +41,8 @@ public void onInit(CallbackInfoReturnable<Boolean> cir) {
4141
if (Settings.bukkitPluginConfig.hookResidence) {
4242
final String res = "Residence";
4343
if (Bukkit.getPluginManager().isPluginEnabled(res)) {
44-
ListenerUtils.registerListenerToTargetPlugin(ResHookEntityChangeBlockListener.class, res);
45-
ListenerUtils.registerListenerToTargetPlugin(ResHookBlockFormListener.class, res);
44+
ListenerHackery.registerListenerToTargetPlugin(ResHookEntityChangeBlockListener.class, res);
45+
ListenerHackery.registerListenerToTargetPlugin(ResHookBlockFormListener.class, res);
4646
HybridFix.LOGGER.info("{}[HybridFix] Hooked into Residence.", ChatColor.AQUA);
4747
} else {
4848
HybridFix.LOGGER.warn("[HybridFix] Residence not found, check your installation.");
@@ -51,7 +51,7 @@ public void onInit(CallbackInfoReturnable<Boolean> cir) {
5151
if (Settings.bukkitPluginConfig.hookWorldGuard) {
5252
final String wg = "WorldGuard";
5353
if (Bukkit.getPluginManager().isPluginEnabled(wg)) {
54-
ListenerUtils.registerListenerToTargetPlugin(WGHookEntityChangeBlockListener.class, wg);
54+
ListenerHackery.registerListenerToTargetPlugin(WGHookEntityChangeBlockListener.class, wg);
5555
HybridFix.LOGGER.info("{}[HybridFix] Hooked into WorldGuard.", ChatColor.LIGHT_PURPLE);
5656
} else {
5757
HybridFix.LOGGER.warn("[HybridFix] WorldGuard not found, check your installation.");
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package io.wdsj.hybridfix.mixin.late.so_many_enchantments.enchants;
2+
3+
import com.shultrea.rin.enchantments.base.EnchantmentBase;
4+
import com.shultrea.rin.enchantments.weapon.EnchantmentDisarmament;
5+
import com.shultrea.rin.mixin.vanilla.IEntityLivingMixin;
6+
import com.shultrea.rin.util.compat.CompatUtil;
7+
import com.shultrea.rin.util.compat.RLCombatCompat;
8+
import net.minecraft.enchantment.EnchantmentHelper;
9+
import net.minecraft.entity.EntityLiving;
10+
import net.minecraft.entity.EntityLivingBase;
11+
import net.minecraft.inventory.EntityEquipmentSlot;
12+
import net.minecraft.item.ItemStack;
13+
import net.minecraft.util.EnumHand;
14+
import net.minecraftforge.event.entity.living.LivingAttackEvent;
15+
import net.minecraftforge.event.entity.living.LivingDamageEvent;
16+
import net.minecraftforge.fml.common.eventhandler.EventPriority;
17+
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
18+
import org.spongepowered.asm.mixin.Mixin;
19+
import org.spongepowered.asm.mixin.Unique;
20+
import org.spongepowered.asm.mixin.injection.At;
21+
import org.spongepowered.asm.mixin.injection.Inject;
22+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
23+
24+
@Mixin(value = EnchantmentDisarmament.class, remap = false)
25+
public abstract class EnchantmentDisarmamentMixin extends EnchantmentBase {
26+
27+
public EnchantmentDisarmamentMixin(String name, Rarity rarity, EntityEquipmentSlot... slots) {
28+
super(name, rarity, slots);
29+
}
30+
31+
@Inject(
32+
method = "onLivingAttackEvent",
33+
at = @At(
34+
value = "HEAD"
35+
),
36+
cancellable = true
37+
)
38+
public void onLivingAttackEvent(LivingAttackEvent event, CallbackInfo ci) {
39+
ci.cancel();
40+
}
41+
42+
@Unique
43+
@SubscribeEvent(priority = EventPriority.HIGH)
44+
public void hybridFix$onLivingDamageEvent(LivingDamageEvent event) {
45+
if (!this.isEnabled()) return;
46+
if (!EnchantmentBase.isDamageSourceAllowed(event.getSource())) return;
47+
if (CompatUtil.isRLCombatLoaded() && !RLCombatCompat.isAttackEntityFromStrong()) return;
48+
if (event.getAmount() <= 1.0F) return;
49+
EntityLivingBase attacker = (EntityLivingBase) event.getSource().getTrueSource();
50+
if (attacker == null) return;
51+
EntityLivingBase victim = event.getEntityLiving();
52+
if (victim == null) return;
53+
// if (victim.world.isRemote) return;
54+
ItemStack stack = attacker.getHeldItemMainhand();
55+
if (stack.isEmpty()) return;
56+
57+
int level = EnchantmentHelper.getEnchantmentLevel(this, stack);
58+
if (level > 0) {
59+
if (attacker.getRNG().nextFloat() < 0.02F * (float) level) {
60+
if (!victim.getHeldItemMainhand().isEmpty()) {
61+
if (victim instanceof EntityLiving && attacker.getRNG().nextFloat() >= ((IEntityLivingMixin) victim).getInventoryHandsDropChances()[0])
62+
return;
63+
victim.entityDropItem(victim.getHeldItemMainhand(), 0.5F);
64+
victim.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY);
65+
} else if (!victim.getHeldItemOffhand().isEmpty()) {
66+
if (victim instanceof EntityLiving && attacker.getRNG().nextFloat() >= ((IEntityLivingMixin) victim).getInventoryHandsDropChances()[1])
67+
return;
68+
victim.entityDropItem(victim.getHeldItemOffhand(), 0.5F);
69+
victim.setHeldItem(EnumHand.OFF_HAND, ItemStack.EMPTY);
70+
}
71+
}
72+
}
73+
}
74+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"package": "io.wdsj.hybridfix.mixin.late.so_many_enchantments.enchants",
3+
"required": true,
4+
"refmap": "${mixin_refmap}",
5+
"target": "@env(DEFAULT)",
6+
"minVersion": "0.8",
7+
"compatibilityLevel": "JAVA_8",
8+
"mixins": [
9+
"EnchantmentDisarmamentMixin"
10+
]
11+
}

0 commit comments

Comments
 (0)