Skip to content

Commit bed6c3b

Browse files
committed
ShieldBlockEventWrapper
1 parent bb79f07 commit bed6c3b

8 files changed

Lines changed: 202 additions & 1 deletion

File tree

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package io.github.lounode.eventwrapper.event.entity.living;
2+
3+
import net.minecraft.util.Mth;
4+
import net.minecraft.world.damagesource.DamageSource;
5+
import net.minecraft.world.entity.LivingEntity;
6+
7+
8+
import io.github.lounode.eventwrapper.eventbus.api.Cancelable;
9+
10+
/**
11+
* The ShieldBlockEvent is fired when an entity successfully blocks with a shield.<br>
12+
* Cancelling this event will have the same impact as if the shield was not eligible to block.<br>
13+
* The damage blocked cannot be set lower than zero or greater than the original value.<br>
14+
* Note: The shield item stack "should" be available from {@link LivingEntity#getUseItem()}
15+
* at least for players.
16+
*/
17+
@Cancelable
18+
public class ShieldBlockEventWrapper extends LivingEventWrapper {
19+
private final DamageSource source;
20+
private final float originalBlocked;
21+
private float dmgBlocked;
22+
private boolean shieldTakesDamage = true;
23+
24+
public ShieldBlockEventWrapper(LivingEntity blocker, DamageSource source, float blocked) {
25+
super(blocker);
26+
this.source = source;
27+
this.originalBlocked = blocked;
28+
this.dmgBlocked = blocked;
29+
}
30+
31+
/**
32+
* @return The damage source.
33+
*/
34+
public DamageSource getDamageSource() {
35+
return this.source;
36+
}
37+
38+
/**
39+
* @return The original amount of damage blocked, which is the same as the original
40+
* incoming damage value.
41+
*/
42+
public float getOriginalBlockedDamage() {
43+
return this.originalBlocked;
44+
}
45+
46+
/**
47+
* @return The current amount of damage blocked, as a result of this event.
48+
*/
49+
public float getBlockedDamage() {
50+
return this.dmgBlocked;
51+
}
52+
53+
/**
54+
* Controls if {@link LivingEntity#hurtCurrentlyUsedShield} is called.
55+
*
56+
* @return If the shield item will take durability damage or not.
57+
*/
58+
public boolean shieldTakesDamage() {
59+
return this.shieldTakesDamage;
60+
}
61+
62+
/**
63+
* Set how much damage is blocked by this action.<br>
64+
* Note that initially the blocked amount is the entire attack.<br>
65+
*/
66+
public void setBlockedDamage(float blocked) {
67+
this.dmgBlocked = Mth.clamp(blocked, 0.0F, this.originalBlocked);
68+
}
69+
70+
/**
71+
* Set if the shield will take durability damage or not.
72+
*/
73+
public void setShieldTakesDamage(boolean damage) {
74+
this.shieldTakesDamage = damage;
75+
}
76+
}

fabric/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ loom {
7474
client{
7575
vmArg "-DdebugEvent=true"
7676
vmArg "-XX:+AllowEnhancedClassRedefinition"
77+
vmArg "-Dmixin.debug=true"
7778
}
7879

7980
gameTest {

fabric/src/main/java/io/github/lounode/eventwrapper/fabric/EventWrapperHooks.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import io.github.lounode.eventwrapper.event.PlayLevelSoundEventWrapper;
4646
import io.github.lounode.eventwrapper.event.entity.living.LivingDeathEventWrapper;
4747
import io.github.lounode.eventwrapper.event.entity.living.MobEffectEventWrapper;
48+
import io.github.lounode.eventwrapper.event.entity.living.ShieldBlockEventWrapper;
4849
import io.github.lounode.eventwrapper.event.entity.player.AnvilRepairEventWrapper;
4950
import io.github.lounode.eventwrapper.event.entity.player.EntityItemPickupEventWrapper;
5051
import io.github.lounode.eventwrapper.event.entity.player.PlayerEventWrapper;
@@ -296,4 +297,10 @@ public static WeightedRandomList<MobSpawnSettings.SpawnerData> getPotentialSpawn
296297
}
297298
return WeightedRandomList.create(event.getSpawnerDataList());
298299
}
300+
301+
public static ShieldBlockEventWrapper onShieldBlock(LivingEntity blocker, DamageSource source, float blocked) {
302+
ShieldBlockEventWrapper e = new ShieldBlockEventWrapper(blocker, source, blocked);
303+
EventsWrapper.post(e);
304+
return e;
305+
}
299306
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package io.github.lounode.eventwrapper.fabric.mixin.eventposter.entity.living.shield_block_event;
2+
3+
import com.llamalad7.mixinextras.injector.WrapWithCondition;
4+
import com.llamalad7.mixinextras.sugar.Local;
5+
import com.llamalad7.mixinextras.sugar.Share;
6+
import com.llamalad7.mixinextras.sugar.ref.LocalFloatRef;
7+
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
8+
9+
import net.minecraft.world.damagesource.DamageSource;
10+
import net.minecraft.world.entity.LivingEntity;
11+
12+
import org.spongepowered.asm.mixin.Mixin;
13+
import org.spongepowered.asm.mixin.injection.At;
14+
import org.spongepowered.asm.mixin.injection.Inject;
15+
import org.spongepowered.asm.mixin.injection.ModifyVariable;
16+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
17+
18+
19+
import io.github.lounode.eventwrapper.event.entity.living.ShieldBlockEventWrapper;
20+
import io.github.lounode.eventwrapper.fabric.EventWrapperHooks;
21+
22+
@Mixin(LivingEntity.class)
23+
public class EventPosterLivingEntity {
24+
25+
@Inject(
26+
method = "hurt",
27+
at = @At(
28+
value = "INVOKE",
29+
target = "Lnet/minecraft/world/entity/LivingEntity;isDamageSourceBlocked(Lnet/minecraft/world/damagesource/DamageSource;)Z",
30+
shift = At.Shift.AFTER
31+
)
32+
)
33+
private void onAfterTestBlock(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir, @Share("wrapper") LocalRef<ShieldBlockEventWrapper> wrapper) {
34+
var event = EventWrapperHooks.onShieldBlock((LivingEntity) (Object) this, source, amount);
35+
wrapper.set(event);
36+
}
37+
38+
@WrapWithCondition(
39+
method = "hurt",
40+
at = @At(
41+
value = "INVOKE",
42+
target = "Lnet/minecraft/world/entity/LivingEntity;hurtCurrentlyUsedShield(F)V"
43+
)
44+
)
45+
private boolean onHurtCurrentlyUsedShield(LivingEntity instance, float damageAmount, @Share("wrapper") LocalRef<ShieldBlockEventWrapper> wrapper) {
46+
var event = wrapper.get();
47+
if (event.isCanceled() || !event.shieldTakesDamage()) {
48+
return false;
49+
}
50+
51+
return true;
52+
}
53+
54+
//BUG FEATURE: We ignore stats damage change, It's too hard and may course some issue
55+
56+
@WrapWithCondition(
57+
method = "hurt",
58+
at = @At(
59+
value = "INVOKE",
60+
target = "Lnet/minecraft/world/entity/LivingEntity;blockUsingShield(Lnet/minecraft/world/entity/LivingEntity;)V"
61+
)
62+
)
63+
private boolean onNonProjectileBlocked(LivingEntity instance, LivingEntity attacker, @Local(argsOnly = true) DamageSource source, @Share("wrapper") LocalRef<ShieldBlockEventWrapper> wrapper) {
64+
var event = wrapper.get();
65+
if (event.isCanceled()) {
66+
return false;
67+
}
68+
return true;
69+
}
70+
71+
@ModifyVariable(
72+
method = "hurt",
73+
at = @At(
74+
value = "STORE",
75+
ordinal = 1
76+
),
77+
ordinal = 0
78+
)
79+
private boolean modifyBlFlag(boolean original, @Local(argsOnly = true) LocalFloatRef amount, @Share("wrapper") LocalRef<ShieldBlockEventWrapper> wrapper) {
80+
var event = wrapper.get();
81+
if (!event.isCanceled() && original) {
82+
float am = event.getOriginalBlockedDamage() - event.getBlockedDamage();
83+
amount.set(am);
84+
return am <= 0;
85+
}
86+
return original;
87+
}
88+
}

fabric/src/main/resources/eventwrapper_fabric.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"eventposter.entity.living.living_death_event.EventPosterLivingEntity",
2121
"eventposter.entity.living.living_death_event.EventPosterPlayer",
2222
"eventposter.entity.living.living_death_event.EventPosterServerPlayer",
23+
"eventposter.entity.living.shield_block_event.EventPosterLivingEntity",
2324
"eventposter.entity.player.AnvilRepairEventPoster",
2425
"eventposter.entity.player.AttackEntityEventPoster",
2526
"eventposter.entity.player.playerevent.PlayerEventBreakSpeedEventPoster",

forge/src/main/java/io/github/lounode/eventwrapper/forge/event/ForgeEventMappings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ public static Class<? extends EventWrapper> getWrapperClass(Class<? extends Even
124124
makeLink(LivingEvent.LivingTickEvent.class, LivingEventWrapper.LivingTickEvent.class, new LivingEventConverter.LivingTickConverter());
125125
makeLink(LivingEvent.LivingVisibilityEvent.class, LivingEventWrapper.LivingVisibilityEvent.class, new LivingEventConverter.LivingVisibilityConverter());
126126
makeLink(LivingDeathEvent.class, LivingDeathEventWrapper.class, new LivingDeathEventConverter());
127+
makeLink(ShieldBlockEvent.class, ShieldBlockEventWrapper.class, new ShieldBlockEventConverter());
127128

128129
//Other
129130
makeLink(PlayLevelSoundEvent.AtEntity.class, PlayLevelSoundEventWrapper.AtEntity.class, new PlayLevelSoundEventConverter.AtEntity());
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.github.lounode.eventwrapper.forge.event.converter.entity.living;
2+
3+
import net.minecraftforge.event.entity.living.ShieldBlockEvent;
4+
5+
6+
import io.github.lounode.eventwrapper.event.entity.living.ShieldBlockEventWrapper;
7+
import io.github.lounode.eventwrapper.forge.event.converter.ForgeEventConverter;
8+
9+
public class ShieldBlockEventConverter implements ForgeEventConverter<ShieldBlockEvent, ShieldBlockEventWrapper> {
10+
@Override
11+
public ShieldBlockEvent toEvent(ShieldBlockEventWrapper wrapper) {
12+
var event = new ShieldBlockEvent(wrapper.getEntity(), wrapper.getDamageSource(), wrapper.getOriginalBlockedDamage());
13+
event.setCanceled(wrapper.isCanceled());
14+
event.setBlockedDamage(wrapper.getBlockedDamage());
15+
event.setShieldTakesDamage(wrapper.shieldTakesDamage());
16+
return event;
17+
}
18+
19+
@Override
20+
public ShieldBlockEventWrapper toWrapper(ShieldBlockEvent event) {
21+
var wrapper = new ShieldBlockEventWrapper(event.getEntity(), event.getDamageSource(), event.getOriginalBlockedDamage());
22+
wrapper.setCanceled(event.isCanceled());
23+
wrapper.setBlockedDamage(event.getBlockedDamage());
24+
wrapper.setShieldTakesDamage(event.shieldTakesDamage());
25+
return wrapper;
26+
}
27+
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ artifact_name = EventWrapper
2828
mod_id=eventwrapper
2929
mod_name=Event Wrapper
3030
mod_license=MIT License
31-
mod_version=1.1.2
31+
mod_version=1.1.3
3232
mod_group_id=io.github.lounode.eventwrapper
3333
mod_logo=assets/eventwrapper/textures/logo.png
3434
mod_authors=Lounode

0 commit comments

Comments
 (0)