Skip to content

Commit 1894ccc

Browse files
committed
Add cannot_run curse
1 parent de9018e commit 1894ccc

7 files changed

Lines changed: 131 additions & 69 deletions

File tree

src/main/java/huix/infinity/common/world/curse/CurseEffectHelper.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
package huix.infinity.common.world.curse;
22

3+
import huix.infinity.common.core.tag.IFWItemTags;
34
import huix.infinity.common.world.item.IFWItems;
45
import huix.infinity.extension.func.PlayerExtension;
6+
import huix.infinity.init.event.IFWSoundEvents;
57
import huix.infinity.network.ClientBoundSetCursePayload;
68
import huix.infinity.util.ReflectHelper;
9+
import net.minecraft.core.Holder;
10+
import net.minecraft.core.registries.BuiltInRegistries;
711
import net.minecraft.server.level.ServerPlayer;
12+
import net.minecraft.sounds.SoundSource;
13+
import net.minecraft.tags.FluidTags;
14+
import net.minecraft.world.entity.monster.EnderMan;
815
import net.minecraft.world.entity.player.Player;
16+
import net.minecraft.world.item.Item;
917
import net.minecraft.world.item.ItemStack;
18+
import net.minecraft.world.level.block.Block;
1019
import net.neoforged.neoforge.network.PacketDistributor;
1120

1221
public class CurseEffectHelper {
@@ -51,4 +60,76 @@ public static void learnCurseEffect(PlayerExtension ext) {
5160
}
5261
}
5362
}
63+
64+
public static boolean shouldBlockSprint(Player player) {
65+
if (!(player instanceof PlayerExtension ext)) return false;
66+
if (ext.getCurse() == CurseType.cannot_run) {
67+
learnCurseEffect(ext);
68+
return true;
69+
}
70+
return false;
71+
}
72+
73+
public static int getCursedMaxAirSupply(Player player, int vanillaMaxAir) {
74+
if (!(player instanceof PlayerExtension ext)) return vanillaMaxAir;
75+
if (ext.getCurse() == CurseType.cannot_hold_breath) {
76+
return 90;
77+
}
78+
return vanillaMaxAir;
79+
}
80+
81+
public static int getCursedAirSupply(Player player, int vanillaAir) {
82+
if (!(player instanceof PlayerExtension ext)) return vanillaAir;
83+
if (ext.getCurse() == CurseType.cannot_hold_breath && player.isEyeInFluid(FluidTags.WATER)) {
84+
learnCurseEffect(ext);
85+
return 90;
86+
}
87+
return vanillaAir;
88+
}
89+
90+
public static int getCursedBubbleMax(Player player, int vanillaBubbleMax, int maxAirSupply) {
91+
if (!(player instanceof PlayerExtension ext)) return vanillaBubbleMax;
92+
if (ext.getCurse() == CurseType.cannot_hold_breath) {
93+
return Math.max(1, maxAirSupply / 30);
94+
}
95+
return vanillaBubbleMax;
96+
}
97+
98+
public static boolean handleChestCurse(Player player, Block block) {
99+
if (!(player instanceof PlayerExtension ext)) return false;
100+
if (ext.getCurse() == CurseType.cannot_open_chests) {
101+
Item item = Item.BY_BLOCK.get(block);
102+
if (item != null) {
103+
Holder<Item> holder = BuiltInRegistries.ITEM.wrapAsHolder(item);
104+
if (holder.is(IFWItemTags.CHESTS)) {
105+
learnCurseEffect(ext);
106+
player.level().playSound(null, player.getX(), player.getY(), player.getZ(), IFWSoundEvents.CHEST_LOCKED.get(), SoundSource.BLOCKS, 0.2F, 1.0F);
107+
return true;
108+
}
109+
}
110+
}
111+
return false;
112+
}
113+
114+
public static void handleEndermanAggro(EnderMan enderman) {
115+
PlayerExtension nearestExt = null;
116+
Player nearestPlayer = null;
117+
double nearestDist = Double.MAX_VALUE;
118+
for (Player player : enderman.level().players()) {
119+
if (player instanceof PlayerExtension ext && ext.getCurse() == CurseType.endermen_aggro) {
120+
double dist = enderman.distanceTo(player);
121+
if (dist < nearestDist) {
122+
nearestDist = dist;
123+
nearestPlayer = player;
124+
nearestExt = ext;
125+
}
126+
}
127+
}
128+
if (nearestPlayer != null) {
129+
enderman.setTarget(nearestPlayer);
130+
if (enderman.getTarget() == nearestPlayer) {
131+
learnCurseEffect(nearestExt);
132+
}
133+
}
134+
}
54135
}

src/main/java/huix/infinity/common/world/curse/CurseManager.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public void removeCursesForWitch(UUID witchUuid, Collection<ServerPlayer> online
3434
curses.removeIf(curse -> curse.witchUuid.equals(witchUuid));
3535
for (UUID playerUuid : affectedPlayers) {
3636
ServerPlayer online = getOnlinePlayerByUUID(playerUuid, onlinePlayers);
37-
if (online != null && online instanceof PlayerExtension ext) {
37+
if (online instanceof PlayerExtension ext) {
3838
ext.ifw$setCurse(CurseType.none);
3939
ext.setKnownCurse(false);
4040
syncCurseRemoved(online);
@@ -74,6 +74,21 @@ public boolean playerHasCursePending(UUID playerUuid) {
7474
return false;
7575
}
7676

77+
public void processPendingCurseClear(Collection<ServerPlayer> players) {
78+
Iterator<UUID> iter = pendingCurseClear.iterator();
79+
while (iter.hasNext()) {
80+
UUID uuid = iter.next();
81+
for (ServerPlayer player : players) {
82+
if (player.getUUID().equals(uuid) && player instanceof PlayerExtension ext) {
83+
ext.ifw$setCurse(CurseType.none);
84+
INSTANCE.syncCurseRemoved(player);
85+
iter.remove();
86+
break;
87+
}
88+
}
89+
}
90+
}
91+
7792
public void tick(Collection<ServerPlayer> players) {
7893
long now = System.currentTimeMillis();
7994
for (Curse curse : curses) {
Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
package huix.infinity.common.world.curse;
22

3-
import huix.infinity.extension.func.PlayerExtension;
43
import net.minecraft.server.level.ServerPlayer;
54
import net.neoforged.bus.api.SubscribeEvent;
65
import net.neoforged.fml.common.EventBusSubscriber;
76
import net.neoforged.neoforge.event.tick.ServerTickEvent;
87

98
import java.util.Collection;
10-
import java.util.Iterator;
11-
import java.util.Set;
12-
import java.util.UUID;
139

1410
@EventBusSubscriber
1511
public class CurseManagerTickHandler {
@@ -18,19 +14,6 @@ public class CurseManagerTickHandler {
1814
public static void onServerTick(ServerTickEvent.Post event) {
1915
Collection<ServerPlayer> players = event.getServer().getPlayerList().getPlayers();
2016
CurseManager.INSTANCE.tick(players);
21-
22-
Set<UUID> pending = CurseManager.pendingCurseClear;
23-
Iterator<UUID> iter = pending.iterator();
24-
while (iter.hasNext()) {
25-
UUID uuid = iter.next();
26-
for (ServerPlayer player : players) {
27-
if (player.getUUID().equals(uuid) && player instanceof PlayerExtension ext) {
28-
ext.ifw$setCurse(CurseType.none);
29-
CurseManager.INSTANCE.syncCurseRemoved(player);
30-
iter.remove();
31-
break;
32-
}
33-
}
34-
}
17+
CurseManager.INSTANCE.processPendingCurseClear(players);
3518
}
3619
}

src/main/java/huix/infinity/init/IFWEvents.java

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import huix.infinity.attachment.IFWAttachments;
44
import huix.infinity.common.core.component.IFWDataComponents;
5-
import huix.infinity.common.core.tag.IFWItemTags;
65
import huix.infinity.common.world.curse.CurseEffectHelper;
76
import huix.infinity.common.world.curse.CurseType;
87
import huix.infinity.common.world.effect.UnClearEffect;
@@ -13,25 +12,20 @@
1312
import huix.infinity.compat.farmersdelight.FDEventHandler;
1413
import huix.infinity.compat.farmersdelight.FDFoodAdapter;
1514
import huix.infinity.extension.func.FoodDataExtension;
16-
import huix.infinity.extension.func.PlayerExtension;
1715
import huix.infinity.init.event.IFWLoading;
18-
import huix.infinity.init.event.IFWSoundEvents;
1916
import huix.infinity.util.IFWEnchantmentHelper;
2017
import huix.infinity.util.WorldHelper;
2118
import net.minecraft.ChatFormatting;
2219
import net.minecraft.client.Minecraft;
2320
import net.minecraft.client.gui.screens.Screen;
2421
import net.minecraft.client.player.LocalPlayer;
2522
import net.minecraft.core.BlockPos;
26-
import net.minecraft.core.Holder;
2723
import net.minecraft.core.component.DataComponents;
28-
import net.minecraft.core.registries.BuiltInRegistries;
2924
import net.minecraft.network.chat.Component;
3025
import net.minecraft.resources.ResourceKey;
3126
import net.minecraft.resources.ResourceLocation;
3227
import net.minecraft.server.level.ServerLevel;
3328
import net.minecraft.server.level.ServerPlayer;
34-
import net.minecraft.sounds.SoundSource;
3529
import net.minecraft.tags.ItemTags;
3630
import net.minecraft.world.effect.MobEffects;
3731
import net.minecraft.world.entity.EquipmentSlot;
@@ -426,18 +420,9 @@ public static void onPlayerUseItem(LivingEntityUseItemEvent.Start event) {
426420
@SubscribeEvent
427421
public static void onPlayerInteractBlock(PlayerInteractEvent.RightClickBlock event) {
428422
Player player = event.getEntity();
429-
if (!(player instanceof PlayerExtension ext)) return;
430-
if (ext.getCurse() == CurseType.cannot_open_chests) {
431-
Block block = event.getLevel().getBlockState(event.getPos()).getBlock();
432-
Item item = Item.BY_BLOCK.get(block);
433-
if (item != null) {
434-
Holder<Item> holder = BuiltInRegistries.ITEM.wrapAsHolder(item);
435-
if (holder.is(IFWItemTags.CHESTS)) {
436-
CurseEffectHelper.learnCurseEffect(ext);
437-
player.level().playSound(null, player.getX(), player.getY(), player.getZ(), IFWSoundEvents.CHEST_LOCKED.get(), SoundSource.BLOCKS, 0.2F, 1.0F);
438-
event.setCanceled(true);
439-
}
440-
}
423+
Block block = event.getLevel().getBlockState(event.getPos()).getBlock();
424+
if (CurseEffectHelper.handleChestCurse(player, block)) {
425+
event.setCanceled(true);
441426
}
442427
}
443428
}

src/main/java/huix/infinity/mixin/client/GuiMixin.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import com.llamalad7.mixinextras.sugar.Local;
44
import com.mojang.blaze3d.systems.RenderSystem;
5-
import huix.infinity.common.world.curse.CurseType;
6-
import huix.infinity.extension.func.PlayerExtension;
5+
import huix.infinity.common.world.curse.CurseEffectHelper;
76
import net.minecraft.client.DeltaTracker;
87
import net.minecraft.client.Minecraft;
98
import net.minecraft.client.gui.Font;
@@ -66,13 +65,10 @@ private void fixRenderXP(GuiGraphics guiGraphics, DeltaTracker deltaTracker, Cal
6665
int i1 = p_283143_.guiWidth() / 2 + 91;
6766
int i3 = player.getMaxAirSupply();
6867
int j3 = Math.min(player.getAirSupply(), i3);
68+
6969
if (player.isEyeInFluid(net.minecraft.tags.FluidTags.WATER) || j3 < i3) {
70-
int bubblesMax = 10;
71-
if (player instanceof PlayerExtension ext
72-
&& ext.getCurse() == CurseType.cannot_hold_breath) {
73-
bubblesMax = Math.max(1, i3 / 30);
74-
}
75-
int bubblesCurrent = Mth.ceil((double)j3 * bubblesMax / (double)i3);
70+
int bubblesMax = CurseEffectHelper.getCursedBubbleMax(player, 10, i3);
71+
int bubblesCurrent = Mth.ceil((double) j3 * bubblesMax / (double) i3);
7672
int j2 = p_283143_.guiHeight() - this.rightHeight;
7773
RenderSystem.enableBlend();
7874
for (int j4 = 0; j4 < bubblesCurrent; ++j4) {
Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,43 @@
11
package huix.infinity.mixin.world.entity;
22

3-
import net.minecraft.tags.FluidTags;
43
import net.minecraft.world.entity.Entity;
54
import net.minecraft.world.entity.player.Player;
6-
import huix.infinity.extension.func.PlayerExtension;
7-
import huix.infinity.common.world.curse.CurseType;
85
import huix.infinity.common.world.curse.CurseEffectHelper;
96
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.gen.Invoker;
108
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Redirect;
1110
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
1211
import org.spongepowered.asm.mixin.injection.Inject;
1312

1413
@Mixin(Entity.class)
15-
public class EntityMixin {
14+
public abstract class EntityMixin {
1615

1716
@Inject(method = "getMaxAirSupply", at = @At("HEAD"), cancellable = true)
1817
private void ifw$setMaxAirSupply(CallbackInfoReturnable<Integer> cir) {
19-
if ((Object)this instanceof Player player && player instanceof PlayerExtension ext) {
20-
int maxAir = 300;
21-
if (ext.getCurse() == CurseType.cannot_hold_breath) {
22-
maxAir = 90;
23-
}
24-
cir.setReturnValue(maxAir);
18+
if ((Object)this instanceof Player player) {
19+
int vanillaMaxAir = 300;
20+
cir.setReturnValue(CurseEffectHelper.getCursedMaxAirSupply(player, vanillaMaxAir));
2521
}
2622
}
2723

2824
@Inject(method = "getAirSupply", at = @At("RETURN"), cancellable = true)
2925
private void ifw$limitAirSupply(CallbackInfoReturnable<Integer> cir) {
30-
if ((Object)this instanceof Player player && player instanceof PlayerExtension ext) {
31-
if (ext.getCurse() == CurseType.cannot_hold_breath && player.isEyeInFluid(FluidTags.WATER)) {
32-
CurseEffectHelper.learnCurseEffect(ext);
33-
cir.setReturnValue(90);
34-
}
26+
if ((Object)this instanceof Player player) {
27+
int vanillaAir = cir.getReturnValue();
28+
cir.setReturnValue(CurseEffectHelper.getCursedAirSupply(player, vanillaAir));
29+
}
30+
}
31+
32+
@Invoker("setSharedFlag")
33+
protected abstract void invokeSetSharedFlag(int flag, boolean value);
34+
35+
@Redirect(method = "setSprinting", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSharedFlag(IZ)V"))
36+
private void ifw$blockSetSprintFlag(Entity entity, int flag, boolean value) {
37+
if (entity instanceof Player player && flag == 3 && value && CurseEffectHelper.shouldBlockSprint(player)) {
38+
((EntityMixin)(Object)entity).invokeSetSharedFlag(flag, false);
39+
} else {
40+
((EntityMixin)(Object)entity).invokeSetSharedFlag(flag, value);
3541
}
3642
}
3743
}
Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
package huix.infinity.mixin.world.entity.monster;
22

3-
import huix.infinity.common.world.curse.CurseType;
4-
import huix.infinity.extension.func.PlayerExtension;
3+
import huix.infinity.common.world.curse.CurseEffectHelper;
54
import net.minecraft.world.entity.monster.EnderMan;
6-
import net.minecraft.world.entity.player.Player;
75
import org.spongepowered.asm.mixin.Mixin;
86
import org.spongepowered.asm.mixin.injection.At;
97
import org.spongepowered.asm.mixin.injection.Inject;
10-
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
8+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
119

1210
@Mixin(EnderMan.class)
1311
public class EnderManMixin {
1412

15-
@Inject(method = "isLookingAtMe", at = @At("HEAD"), cancellable = true)
16-
private void ifw$forceEndermanAggro(Player player, CallbackInfoReturnable<Boolean> cir) {
17-
if (player instanceof PlayerExtension ext && ext.getCurse() == CurseType.endermen_aggro) {
18-
cir.setReturnValue(true);
19-
}
13+
@Inject(method = "aiStep", at = @At("HEAD"))
14+
private void ifw$forceEndermanAttack(CallbackInfo ci) {
15+
CurseEffectHelper.handleEndermanAggro((EnderMan)(Object)this);
2016
}
2117
}

0 commit comments

Comments
 (0)