package slimeknights.tconstruct.library; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import java.util.IdentityHashMap; public class SlimeBounceHandler { private static final IdentityHashMap<Entity, SlimeBounceHandler> bouncingEntities = new IdentityHashMap<Entity, SlimeBounceHandler>(); public final EntityLivingBase entityLiving; private int timer; private boolean wasInAir; private double bounce; private int bounceTick; private double lastMovX; private double lastMovZ; public SlimeBounceHandler(EntityLivingBase entityLiving, double bounce) { this.entityLiving = entityLiving; timer = 0; wasInAir = false; this.bounce = bounce; if(bounce != 0) { bounceTick = entityLiving.ticksExisted; } else { bounceTick = 0; } bouncingEntities.put(entityLiving, this); //entityLiving.addChatMessage(new ChatComponentText("added " + entityLiving.worldObj.isRemote)); } @SubscribeEvent public void playerTickPost(TickEvent.PlayerTickEvent event) { // this is only relevant for the local player if(event.phase == TickEvent.Phase.END && event.player == entityLiving && !event.player.isElytraFlying()) { // bounce up. This is to pcircumvent the logic that resets y motion after landing if(event.player.ticksExisted == bounceTick) { event.player.motionY = bounce; bounceTick = 0; } // preserve motion if(!entityLiving.onGround && entityLiving.ticksExisted != bounceTick) { if(lastMovX != entityLiving.motionX || lastMovZ != entityLiving.motionZ) { double f = 0.91d + 0.025d; //System.out.println((entityLiving.worldObj.isRemote ? "client: " : "server: ") + entityLiving.motionX); entityLiving.motionX /= f; entityLiving.motionZ /= f; entityLiving.isAirBorne = true; lastMovX = entityLiving.motionX; lastMovZ = entityLiving.motionZ; } } // timing the effect out if(wasInAir && entityLiving.onGround) { if(timer == 0) { timer = entityLiving.ticksExisted; } else if(entityLiving.ticksExisted - timer > 5) { MinecraftForge.EVENT_BUS.unregister(this); bouncingEntities.remove(entityLiving); //entityLiving.addChatMessage(new ChatComponentText("removed " + entityLiving.worldObj.isRemote)); } } else { timer = 0; wasInAir = true; } } } public static void addBounceHandler(EntityLivingBase entity) { addBounceHandler(entity, 0d); } public static void addBounceHandler(EntityLivingBase entity, double bounce) { // only supports actual players as it uses the PlayerTick event if(!(entity instanceof EntityPlayer) || entity instanceof FakePlayer) { return; } SlimeBounceHandler handler = bouncingEntities.get(entity); if(handler == null) { // wasn't bouncing yet, register it MinecraftForge.EVENT_BUS.register(new SlimeBounceHandler(entity, bounce)); } else if(bounce != 0) { // updated bounce if needed handler.bounce = bounce; handler.bounceTick = entity.ticksExisted; } } }