diff --git a/src/main/java/com/minelittlepony/unicopia/player/PlayerAttributes.java b/src/main/java/com/minelittlepony/unicopia/player/PlayerAttributes.java index cb293c03..54b4c0f1 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/PlayerAttributes.java +++ b/src/main/java/com/minelittlepony/unicopia/player/PlayerAttributes.java @@ -28,6 +28,8 @@ class PlayerAttributes { private double loadStrength = 0; + private final WalkSpeed walker = new WalkSpeed(); + public void applyAttributes(EntityPlayer entity, Race race) { loadStrength = 0; @@ -38,9 +40,7 @@ class PlayerAttributes { loadStrength += InventoryOfHolding.decodeStackWeight(item); } - if (entity.world.isRemote) { - entity.capabilities.setPlayerWalkSpeed(0.1F - (float)(loadStrength / 100000)); - } + walker.setPlayerWalkSpeed(entity.capabilities, 0.1F - (float)(loadStrength / 100000)); applyAttribute(entity, SharedMonsterAttributes.ATTACK_DAMAGE, EARTH_PONY_STRENGTH, race.canUseEarth()); applyAttribute(entity, SharedMonsterAttributes.KNOCKBACK_RESISTANCE, EARTH_PONY_STRENGTH, race.canUseEarth()); diff --git a/src/main/java/com/minelittlepony/unicopia/player/WalkSpeed.java b/src/main/java/com/minelittlepony/unicopia/player/WalkSpeed.java new file mode 100644 index 00000000..441bfe8f --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/player/WalkSpeed.java @@ -0,0 +1,72 @@ +package com.minelittlepony.unicopia.player; + +import java.lang.reflect.Field; + +import com.minelittlepony.unicopia.forgebullshit.FUF; + +import net.minecraft.entity.player.PlayerCapabilities; +import net.minecraft.nbt.NBTTagCompound;; + +/** + * Workaround for setting the player's walking speed. + */ +@FUF(reason = "`setPlayerWalkSpeed(v)` is marked as client-only. Waiting on mixins...") +class WalkSpeed { + + private static boolean regularMethodCheck = true; + + private static boolean reflexiveMethodCheck = true; + private static Field walkSpeed; + + public void setPlayerWalkSpeed(PlayerCapabilities capabilities, float speed) { + if (capabilities.getWalkSpeed() == speed) { + return; + } + + if (!setNormally(capabilities, speed)) { + if (!setReflexively(capabilities, speed)) { + setTheMostSlow(capabilities, speed); + } + } + } + + private boolean setNormally(PlayerCapabilities capabilities, float speed) { + if (regularMethodCheck) { + try { + capabilities.setPlayerWalkSpeed(speed); + } catch (Throwable t) { + regularMethodCheck = false; + } + } + + return regularMethodCheck; + } + + private boolean setReflexively(PlayerCapabilities capabilities, float speed) { + if (reflexiveMethodCheck) { + try { + if (walkSpeed == null) { + Field[] f = PlayerCapabilities.class.getDeclaredFields(); + walkSpeed = f[f.length - 1]; + walkSpeed.setAccessible(true); + } + + walkSpeed.set(capabilities, speed); + } catch (Throwable t) { + reflexiveMethodCheck = false; + } + } + + return reflexiveMethodCheck; + } + + private void setTheMostSlow(PlayerCapabilities capabilities, float speed) { + NBTTagCompound comp = new NBTTagCompound(); + + capabilities.writeCapabilitiesToNBT(comp); + + comp.getCompoundTag("capabilities").setFloat("walkSpeed", speed); + + capabilities.readCapabilitiesFromNBT(comp); + } +}