Skip to content

Commit 7d19539

Browse files
committed
Expose a way to modify item attributes from custom Meka Suit and Meka-Tool modules and move some of our enchantment based modules over to using attributes
- Removed soul speed 1 from free runners and instead replaced it with the movement efficiency attribute. This allows free runners to truly make you free! (except from cobwebs, and all those other pesky terms and conditions that apply)
1 parent 4b93c1b commit 7d19539

14 files changed

+182
-78
lines changed

src/api/java/mekanism/api/gear/ICustomModule.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import net.minecraft.world.item.ItemStack;
2020
import net.minecraft.world.item.context.UseOnContext;
2121
import net.neoforged.neoforge.common.ToolAction;
22+
import net.neoforged.neoforge.event.ItemAttributeModifierEvent;
2223
import org.jetbrains.annotations.NotNull;
2324
import org.jetbrains.annotations.Nullable;
2425

@@ -193,6 +194,17 @@ default <MODE extends IRadialMode> boolean setMode(IModule<MODULE> module, Playe
193194
return false;
194195
}
195196

197+
/**
198+
* Called when this module is enabled to modify the attributes of the item this module is installed on. (MekaSuit or Meka-Tool)
199+
*
200+
* @param module Module instance.
201+
* @param event Event that provides helper to use to modify the attributes on the stack.
202+
*
203+
* @since 10.6.3
204+
*/
205+
default void adjustAttributes(IModule<MODULE> module, ItemAttributeModifierEvent event) {
206+
}
207+
196208
/**
197209
* Called when this module is added to an item.
198210
* <p>

src/main/java/mekanism/common/CommonPlayerTickHandler.java

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import mekanism.common.content.gear.IBlastingItem;
1919
import mekanism.common.content.gear.mekasuit.ModuleGravitationalModulatingUnit;
2020
import mekanism.common.content.gear.mekasuit.ModuleHydraulicPropulsionUnit;
21-
import mekanism.common.content.gear.mekasuit.ModuleHydrostaticRepulsorUnit;
2221
import mekanism.common.content.gear.mekasuit.ModuleLocomotiveBoostingUnit;
2322
import mekanism.common.item.gear.ItemFreeRunners;
2423
import mekanism.common.item.gear.ItemMekaSuitArmor;
@@ -47,7 +46,6 @@
4746
import net.minecraft.world.level.block.state.BlockState;
4847
import net.minecraft.world.phys.Vec3;
4948
import net.neoforged.bus.api.SubscribeEvent;
50-
import net.neoforged.neoforge.common.NeoForgeMod;
5149
import net.neoforged.neoforge.common.damagesource.DamageContainer;
5250
import net.neoforged.neoforge.event.entity.EntityInvulnerabilityCheckEvent;
5351
import net.neoforged.neoforge.event.entity.living.LivingEvent.LivingJumpEvent;
@@ -83,12 +81,6 @@ public static float getStepBoost(Player player) {
8381
return hydraulic != null ? hydraulic.getCustomInstance().getStepHeight() : 0F;
8482
}
8583

86-
public static float getSwimBoost(Player player) {
87-
ItemStack legs = player.getItemBySlot(EquipmentSlot.LEGS);
88-
IModule<ModuleHydrostaticRepulsorUnit> swimModule = IModuleHelper.INSTANCE.getIfEnabled(legs, MekanismModules.HYDROSTATIC_REPULSOR_UNIT);
89-
return swimModule != null && swimModule.getCustomInstance().isSwimBoost(swimModule, legs, player) ? 1 : 0;
90-
}
91-
9284
@SubscribeEvent
9385
public void onTick(PlayerTickEvent.Post event) {
9486
if (!event.getEntity().level().isClientSide()) {
@@ -98,7 +90,6 @@ public void onTick(PlayerTickEvent.Post event) {
9890

9991
private void tickEnd(Player player) {
10092
Mekanism.playerState.updateStepAssist(player);
101-
Mekanism.playerState.updateSwimBoost(player);
10293
if (player instanceof ServerPlayer serverPlayer) {
10394
RadiationManager.get().tickServer(serverPlayer);
10495
}
@@ -147,13 +138,13 @@ private void tickEnd(Player player) {
147138
}
148139
}
149140

150-
public static boolean isGravitationalModulationReady(ItemStack stack) {
151-
IModule<ModuleGravitationalModulatingUnit> module = IModuleHelper.INSTANCE.getIfEnabled(stack, MekanismModules.GRAVITATIONAL_MODULATING_UNIT);
152-
return module != null && module.hasEnoughEnergy(stack, MekanismConfig.gear.mekaSuitEnergyUsageGravitationalModulation);
153-
}
154-
155141
public static boolean isGravitationalModulationOn(Player player) {
156-
return ModuleGravitationalModulatingUnit.shouldProcess(player) && isGravitationalModulationReady(player.getItemBySlot(EquipmentSlot.CHEST));
142+
if (ModuleGravitationalModulatingUnit.shouldProcess(player)) {
143+
ItemStack stack = player.getItemBySlot(EquipmentSlot.CHEST);
144+
IModule<ModuleGravitationalModulatingUnit> module = IModuleHelper.INSTANCE.getIfEnabled(stack, MekanismModules.GRAVITATIONAL_MODULATING_UNIT);
145+
return module != null && module.hasEnoughEnergy(stack, MekanismConfig.gear.mekaSuitEnergyUsageGravitationalModulation);
146+
}
147+
return false;
157148
}
158149

159150
@SubscribeEvent
@@ -333,14 +324,8 @@ public void getBreakSpeed(BreakSpeed event) {
333324
}
334325

335326
//Gyroscopic stabilization check
336-
if (IModuleHelper.INSTANCE.isEnabled(player.getItemBySlot(EquipmentSlot.LEGS), MekanismModules.GYROSCOPIC_STABILIZATION_UNIT)) {
337-
if (player.isEyeInFluidType(NeoForgeMod.WATER_TYPE.value())) {
338-
speed /= (float) player.getAttributeValue(Attributes.SUBMERGED_MINING_SPEED);
339-
}
340-
341-
if (!player.onGround()) {
342-
speed *= 5.0F;
343-
}
327+
if (!player.onGround() && IModuleHelper.INSTANCE.isEnabled(player.getItemBySlot(EquipmentSlot.LEGS), MekanismModules.GYROSCOPIC_STABILIZATION_UNIT)) {
328+
speed *= 5.0F;
344329
}
345330

346331
event.setNewSpeed(speed);

src/main/java/mekanism/common/base/PlayerState.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,11 @@
2424
import net.minecraft.world.entity.ai.attributes.Attributes;
2525
import net.minecraft.world.entity.player.Player;
2626
import net.minecraft.world.level.LevelAccessor;
27-
import net.neoforged.neoforge.common.NeoForgeMod;
2827
import net.neoforged.neoforge.network.PacketDistributor;
2928

3029
public class PlayerState {
3130

3231
private static final ResourceLocation STEP_ASSIST_MODIFIER_ID = Mekanism.rl("step_assist");
33-
private static final ResourceLocation SWIM_BOOST_MODIFIER_ID = Mekanism.rl("swim_boost");
3432

3533
private final Set<UUID> activeJetpacks = new ObjectOpenHashSet<>();
3634
private final Set<UUID> activeScubaMasks = new ObjectOpenHashSet<>();
@@ -153,16 +151,6 @@ public void updateStepAssist(Player player) {
153151
updateAttribute(player, Attributes.STEP_HEIGHT, STEP_ASSIST_MODIFIER_ID, CommonPlayerTickHandler::getStepBoost);
154152
}
155153

156-
// ----------------------
157-
//
158-
// Swim boost state tracking
159-
//
160-
// ----------------------
161-
162-
public void updateSwimBoost(Player player) {
163-
updateAttribute(player, NeoForgeMod.SWIM_SPEED, SWIM_BOOST_MODIFIER_ID, CommonPlayerTickHandler::getSwimBoost);
164-
}
165-
166154
//Note: The attributes that currently use this cannot be converted to just being attributes on the items, as they can be disabled based on the player state
167155
private void updateAttribute(Player player, Holder<Attribute> attribute, ResourceLocation id, ToFloatFunction<Player> additionalSupplier) {
168156
AttributeInstance attributeInstance = player.getAttribute(attribute);

src/main/java/mekanism/common/content/gear/IModuleContainerItem.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@
1111
import mekanism.api.text.EnumColor;
1212
import mekanism.api.text.TextComponentUtil;
1313
import mekanism.common.MekanismLang;
14+
import mekanism.common.item.interfaces.IHasConditionalAttributes;
1415
import mekanism.common.item.interfaces.IItemHUDProvider;
1516
import mekanism.common.item.interfaces.IModeItem;
1617
import net.minecraft.network.chat.Component;
1718
import net.minecraft.world.entity.EquipmentSlot;
1819
import net.minecraft.world.entity.player.Player;
1920
import net.minecraft.world.item.ItemStack;
21+
import net.neoforged.neoforge.event.ItemAttributeModifierEvent;
2022
import org.jetbrains.annotations.NotNull;
2123
import org.jetbrains.annotations.Nullable;
2224

23-
public interface IModuleContainerItem extends IModeItem, IItemHUDProvider {
25+
public interface IModuleContainerItem extends IModeItem, IItemHUDProvider, IHasConditionalAttributes {
2426

2527
@Nullable
2628
default IModuleContainer moduleContainer(ItemStack stack) {
@@ -31,6 +33,19 @@ default Collection<? extends IModule<?>> getModules(ItemStack stack) {
3133
return IModuleHelper.INSTANCE.getAllModules(stack);
3234
}
3335

36+
@Override
37+
default void adjustAttributes(ItemAttributeModifierEvent event) {
38+
for (IModule<?> module : getModules(event.getItemStack())) {
39+
if (module.isEnabled()) {
40+
adjustAttributes(module, event);
41+
}
42+
}
43+
}
44+
45+
private <MODULE extends ICustomModule<MODULE>> void adjustAttributes(IModule<MODULE> module, ItemAttributeModifierEvent event) {
46+
module.getCustomInstance().adjustAttributes(module, event);
47+
}
48+
3449
default boolean hasInstalledModules(ItemStack stack) {
3550
IModuleContainer container = moduleContainer(stack);
3651
return container != null && container.installedCount() > 0;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package mekanism.common.content.gear.mekasuit;
2+
3+
import mekanism.api.annotations.ParametersAreNotNullByDefault;
4+
import mekanism.api.gear.ICustomModule;
5+
import mekanism.api.gear.IModule;
6+
import mekanism.common.Mekanism;
7+
import net.minecraft.world.entity.EquipmentSlotGroup;
8+
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
9+
import net.minecraft.world.entity.ai.attributes.Attributes;
10+
import net.neoforged.neoforge.event.ItemAttributeModifierEvent;
11+
12+
@ParametersAreNotNullByDefault
13+
public class GyroscopicStabilizationUnit implements ICustomModule<GyroscopicStabilizationUnit> {
14+
15+
private static final AttributeModifier UNDER_WATER_SPEED = new AttributeModifier(Mekanism.rl("submerged_mining_speed"), 1, AttributeModifier.Operation.ADD_VALUE);
16+
17+
@Override
18+
public void adjustAttributes(IModule<GyroscopicStabilizationUnit> module, ItemAttributeModifierEvent event) {
19+
event.addModifier(Attributes.SUBMERGED_MINING_SPEED, UNDER_WATER_SPEED, EquipmentSlotGroup.LEGS);
20+
}
21+
}

src/main/java/mekanism/common/content/gear/mekasuit/ModuleGravitationalModulatingUnit.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,25 @@
1515
import mekanism.common.config.listener.ConfigBasedCachedFLSupplier;
1616
import mekanism.common.content.gear.mekasuit.ModuleLocomotiveBoostingUnit.SprintBoost;
1717
import mekanism.common.registries.MekanismGameEvents;
18+
import mekanism.common.registries.MekanismItems;
1819
import mekanism.common.util.MekanismUtils;
1920
import mekanism.common.util.MekanismUtils.ResourceType;
2021
import net.minecraft.core.Holder;
2122
import net.minecraft.resources.ResourceLocation;
23+
import net.minecraft.world.entity.EquipmentSlotGroup;
24+
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
25+
import net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation;
2226
import net.minecraft.world.entity.player.Player;
2327
import net.minecraft.world.item.ItemStack;
2428
import net.minecraft.world.level.gameevent.GameEvent;
2529
import net.minecraft.world.phys.Vec3;
30+
import net.neoforged.neoforge.common.NeoForgeMod;
31+
import net.neoforged.neoforge.event.ItemAttributeModifierEvent;
2632

2733
@ParametersAreNotNullByDefault
2834
public record ModuleGravitationalModulatingUnit(SprintBoost speedBoost) implements ICustomModule<ModuleGravitationalModulatingUnit> {
2935

36+
private static final AttributeModifier CREATIVE_FLIGHT_MODIFIER = new AttributeModifier(Mekanism.rl("mekasuit_gravitational_modulation"), 1, Operation.ADD_VALUE);
3037
private static final ConfigBasedCachedFLSupplier BOOST_USAGE = new ConfigBasedCachedFLSupplier(
3138
() -> MekanismConfig.gear.mekaSuitEnergyUsageGravitationalModulation.get().multiply(4),
3239
MekanismConfig.gear.mekaSuitEnergyUsageGravitationalModulation
@@ -54,6 +61,14 @@ public void changeMode(IModule<ModuleGravitationalModulatingUnit> module, Player
5461
module.toggleEnabled(moduleContainer, stack, player, MekanismLang.MODULE_GRAVITATIONAL_MODULATION.translate());
5562
}
5663

64+
@Override
65+
public void adjustAttributes(IModule<ModuleGravitationalModulatingUnit> module, ItemAttributeModifierEvent event) {
66+
ItemStack stack = event.getItemStack();
67+
if (stack.is(MekanismItems.MEKASUIT_BODYARMOR) && module.hasEnoughEnergy(stack, MekanismConfig.gear.mekaSuitEnergyUsageGravitationalModulation)) {
68+
event.addModifier(NeoForgeMod.CREATIVE_FLIGHT, CREATIVE_FLIGHT_MODIFIER, EquipmentSlotGroup.CHEST);
69+
}
70+
}
71+
5772
@Override
5873
public void tickClient(IModule<ModuleGravitationalModulatingUnit> module, IModuleContainer moduleContainer, ItemStack stack, Player player) {
5974
//Client side handling of boost as movement needs to be applied on both the server and the client
Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,51 @@
11
package mekanism.common.content.gear.mekasuit;
22

33
import mekanism.api.annotations.ParametersAreNotNullByDefault;
4-
import mekanism.api.gear.EnchantmentAwareModule;
4+
import mekanism.api.gear.ICustomModule;
55
import mekanism.api.gear.IModule;
66
import mekanism.api.gear.IModuleContainer;
77
import mekanism.common.Mekanism;
88
import mekanism.common.config.MekanismConfig;
9-
import net.minecraft.resources.ResourceKey;
109
import net.minecraft.resources.ResourceLocation;
10+
import net.minecraft.world.entity.EquipmentSlotGroup;
11+
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
12+
import net.minecraft.world.entity.ai.attributes.Attributes;
1113
import net.minecraft.world.entity.player.Player;
1214
import net.minecraft.world.item.ItemStack;
13-
import net.minecraft.world.item.enchantment.Enchantment;
14-
import net.minecraft.world.item.enchantment.Enchantments;
15-
import org.jetbrains.annotations.NotNull;
15+
import net.neoforged.neoforge.common.NeoForgeMod;
16+
import net.neoforged.neoforge.event.ItemAttributeModifierEvent;
1617

1718
@ParametersAreNotNullByDefault
18-
public record ModuleHydrostaticRepulsorUnit(boolean swimBoost) implements EnchantmentAwareModule<ModuleHydrostaticRepulsorUnit> {
19+
public record ModuleHydrostaticRepulsorUnit(boolean swimBoost) implements ICustomModule<ModuleHydrostaticRepulsorUnit> {
1920

21+
private static final ResourceLocation WATER_MOVEMENT = Mekanism.rl("water_movement");
2022
public static final ResourceLocation SWIM_BOOST = Mekanism.rl("swim_boost");
23+
private static final AttributeModifier SWIM_BOOST_MODIFIER = new AttributeModifier(SWIM_BOOST, 1, AttributeModifier.Operation.ADD_VALUE);
2124
public static final int BOOST_STACKS = 4;
2225

2326
public ModuleHydrostaticRepulsorUnit(IModule<ModuleHydrostaticRepulsorUnit> module) {
2427
this(module.getBooleanConfigOrFalse(SWIM_BOOST));
2528
}
2629

27-
@NotNull
2830
@Override
29-
public ResourceKey<Enchantment> enchantment() {
30-
return Enchantments.DEPTH_STRIDER;
31+
public void adjustAttributes(IModule<ModuleHydrostaticRepulsorUnit> module, ItemAttributeModifierEvent event) {
32+
//Clamp out at a max efficiency of one (at three installed units)
33+
//Note: Value copied from default for depth strider
34+
AttributeModifier modifier = new AttributeModifier(WATER_MOVEMENT, Math.min(1, 0.33333334F * module.getInstalledCount()), AttributeModifier.Operation.ADD_VALUE);
35+
event.addModifier(Attributes.WATER_MOVEMENT_EFFICIENCY, modifier, EquipmentSlotGroup.LEGS);
36+
if (isSwimBoost(module, event.getItemStack())) {
37+
event.addModifier(NeoForgeMod.SWIM_SPEED, SWIM_BOOST_MODIFIER, EquipmentSlotGroup.LEGS);
38+
}
3139
}
3240

3341
@Override
3442
public void tickServer(IModule<ModuleHydrostaticRepulsorUnit> module, IModuleContainer moduleContainer, ItemStack stack, Player player) {
35-
if (isSwimBoost(module, stack, player)) {
43+
if (isSwimBoost(module, stack) && !player.getMaxHeightFluidType().isAir()) {
3644
module.useEnergy(player, stack, MekanismConfig.gear.mekaSuitEnergyUsageHydrostaticRepulsion.get());
3745
}
3846
}
3947

40-
public boolean isSwimBoost(IModule<ModuleHydrostaticRepulsorUnit> module, ItemStack stack, Player player) {
41-
return swimBoost && module.getInstalledCount() >= BOOST_STACKS && !player.getMaxHeightFluidType().isAir() &&
42-
module.hasEnoughEnergy(stack, MekanismConfig.gear.mekaSuitEnergyUsageHydrostaticRepulsion);
48+
private boolean isSwimBoost(IModule<ModuleHydrostaticRepulsorUnit> module, ItemStack stack) {
49+
return swimBoost && module.getInstalledCount() >= BOOST_STACKS && module.hasEnoughEnergy(stack, MekanismConfig.gear.mekaSuitEnergyUsageHydrostaticRepulsion);
4350
}
4451
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package mekanism.common.content.gear.mekasuit;
2+
3+
import mekanism.api.annotations.ParametersAreNotNullByDefault;
4+
import mekanism.api.gear.ICustomModule;
5+
import mekanism.api.gear.IModule;
6+
import mekanism.common.Mekanism;
7+
import net.minecraft.resources.ResourceLocation;
8+
import net.minecraft.world.entity.EquipmentSlotGroup;
9+
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
10+
import net.minecraft.world.entity.ai.attributes.Attributes;
11+
import net.neoforged.neoforge.event.ItemAttributeModifierEvent;
12+
13+
@ParametersAreNotNullByDefault
14+
public class MotorizedServoUnit implements ICustomModule<MotorizedServoUnit> {
15+
16+
private static final ResourceLocation SNEAK_SPEED = Mekanism.rl("motorized_servo");
17+
18+
@Override
19+
public void adjustAttributes(IModule<MotorizedServoUnit> module, ItemAttributeModifierEvent event) {
20+
//Note: Value copied from default for swift sneak
21+
AttributeModifier modifier = new AttributeModifier(SNEAK_SPEED, Math.min(1, 0.15F * module.getInstalledCount()), AttributeModifier.Operation.ADD_VALUE);
22+
event.addModifier(Attributes.SNEAKING_SPEED, modifier, EquipmentSlotGroup.LEGS);
23+
}
24+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package mekanism.common.content.gear.mekasuit;
2+
3+
import mekanism.api.annotations.ParametersAreNotNullByDefault;
4+
import mekanism.api.gear.EnchantmentAwareModule;
5+
import mekanism.api.gear.IModule;
6+
import mekanism.common.Mekanism;
7+
import net.minecraft.resources.ResourceKey;
8+
import net.minecraft.resources.ResourceLocation;
9+
import net.minecraft.world.entity.EquipmentSlotGroup;
10+
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
11+
import net.minecraft.world.entity.ai.attributes.Attributes;
12+
import net.minecraft.world.item.enchantment.Enchantment;
13+
import net.minecraft.world.item.enchantment.Enchantments;
14+
import net.neoforged.neoforge.event.ItemAttributeModifierEvent;
15+
import org.jetbrains.annotations.NotNull;
16+
17+
@ParametersAreNotNullByDefault
18+
public class SoulSurferUnit implements EnchantmentAwareModule<SoulSurferUnit> {
19+
20+
private static final ResourceLocation MOVEMENT_EFFICIENCY = Mekanism.rl("movement_efficiency");
21+
22+
@Override
23+
public void adjustAttributes(IModule<SoulSurferUnit> module, ItemAttributeModifierEvent event) {
24+
AttributeModifier modifier = new AttributeModifier(MOVEMENT_EFFICIENCY, Math.min(1, 0.33333334F * module.getInstalledCount()), AttributeModifier.Operation.ADD_VALUE);
25+
event.addModifier(Attributes.MOVEMENT_EFFICIENCY, modifier, EquipmentSlotGroup.FEET);
26+
}
27+
28+
@NotNull
29+
@Override
30+
public ResourceKey<Enchantment> enchantment() {
31+
return Enchantments.SOUL_SPEED;
32+
}
33+
}

0 commit comments

Comments
 (0)