That's one heck of a commit you've got there...

I may have got a bit behind with version control. A lot behind, in fact. Maybe I'll go back and split this sometime - then again, I probably won't. But hey, at least it's here!
This commit is contained in:
Electroblob77
2019-08-18 00:04:18 +01:00
parent 2680d02304
commit f37812be3e
1564 changed files with 47652 additions and 12984 deletions
@@ -0,0 +1,172 @@
package electroblob.wizardry.potion;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.item.ItemArtefact;
import electroblob.wizardry.packet.PacketEndSlowTime;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.spell.SlowTime;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IProjectile;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.event.entity.living.PotionEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.util.List;
@Mod.EventBusSubscriber
public class PotionSlowTime extends PotionMagicEffect implements ISyncedPotion {
// FIXME: Minecarts with entities in them (and, I suspect, any other ridden entities) go crazy when time-slowed
public PotionSlowTime(boolean isBadEffect, int liquidColour){
super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_slow_time.png"));
this.setPotionName("potion." + Wizardry.MODID + ":slow_time");
}
private static double getEffectRadius(){
return Spells.slow_time.getProperty(Spell.EFFECT_RADIUS).doubleValue();
}
public static void unblockNearbyEntities(EntityLivingBase host){
List<Entity> targetsBeyondRange = WizardryUtilities.getEntitiesWithinRadius(getEffectRadius() + 3, host.posX, host.posY, host.posZ, host.world, Entity.class);
targetsBeyondRange.forEach(e -> e.updateBlocked = false);
}
// Not done in performEffect because it's client-inconsistent; it only fires on the client of the player with the
// potion effect, and doesn't fire on the client at all for non-players
private static void performEffectConsistent(EntityLivingBase host, int strength){
boolean stopTime = host instanceof EntityPlayer && ItemArtefact.isArtefactActive((EntityPlayer)host, WizardryItems.charm_stop_time);
int interval = strength * 4 + 6;
// Mark all entities within range
List<Entity> targetsInRange = WizardryUtilities.getEntitiesWithinRadius(getEffectRadius(), host.posX, host.posY, host.posZ, host.world, Entity.class);
targetsInRange.remove(host);
// Other entities with the slow time effect are unaffected
targetsInRange.removeIf(t -> t instanceof EntityLivingBase && ((EntityLivingBase)t).isPotionActive(WizardryPotions.slow_time));
if(!Wizardry.settings.slowTimeAffectsPlayers) targetsInRange.removeIf(t -> t instanceof EntityPlayer);
targetsInRange.removeIf(t -> t instanceof EntityArrow && t.isEntityInsideOpaqueBlock());
for(Entity entity : targetsInRange){
// If time is stopped, block all updates; otherwise block all updates except every [interval] ticks
entity.updateBlocked = stopTime || host.ticksExisted % interval != 0;
if(!stopTime && entity.world.isRemote){
// Client-side movement interpolation (smoothing)
if(entity.onGround) entity.motionY = 0; // Don't ask. It just works.
// if(entity instanceof EntityLivingBase){
// ((EntityLivingBase)entity).prevLimbSwingAmount = ((EntityLivingBase)entity).limbSwingAmount;
// ((EntityLivingBase)entity).swingProgress = ((EntityLivingBase)entity).prevSwingProgress;
// ((EntityLivingBase)entity).renderYawOffset = ((EntityLivingBase)entity).prevRenderYawOffset;
// ((EntityLivingBase)entity).rotationYawHead = ((EntityLivingBase)entity).prevRotationYawHead;
// }
if(entity.updateBlocked){
// When the update is blocked, the entity is moved 1/interval times the distance it would have moved
double x = entity.posX + entity.motionX * 1d / (double)interval;
double y = entity.posY + entity.motionY * 1d / (double)interval;
double z = entity.posZ + entity.motionZ * 1d / (double)interval;
entity.prevPosX = entity.posX;
entity.prevPosY = entity.posY;
entity.prevPosZ = entity.posZ;
entity.posX = x;
entity.posY = y;
entity.posZ = z;
}else{
// When the update is not blocked, the entity is moved BACK 1-1/interval times the distance it moved
// This is because the entity already covered most of that distance when its update was blocked
entity.posX += entity.motionX * 1d / (double)interval;
entity.posY += entity.motionY * 1d / (double)interval;
entity.posZ += entity.motionZ * 1d / (double)interval;
double x = entity.posX - entity.motionX * 1d / (double)interval;
double y = entity.posY - entity.motionY * 1d / (double)interval;
double z = entity.posZ - entity.motionZ * 1d / (double)interval;
entity.prevPosX = x;
entity.prevPosY = y;
entity.prevPosZ = z;
}
}
if(entity.world.isRemote && host.ticksExisted % 2 == 0){
int lifetime = 15;
double dx = (entity.world.rand.nextDouble() - 0.5D) * 2 * (double)entity.width;
double dy = (entity.world.rand.nextDouble() - 0.5D) * 2 * (double)entity.width;
double dz = (entity.world.rand.nextDouble() - 0.5D) * 2 * (double)entity.width;
double x = entity.posX + dx;
double y = entity instanceof IProjectile ? entity.posY + dy : entity.posY + entity.height/2 + dy;
double z = entity.posZ + dz;
ParticleBuilder.create(ParticleBuilder.Type.DUST)
.pos(x, y, z)
.vel(-dx/lifetime, -dy/lifetime, -dz/lifetime)
.clr(0x5be3bb).time(15).spawn(entity.world);
}
}
// Un-mark all entities that have just left range
List<Entity> targetsBeyondRange = WizardryUtilities.getEntitiesWithinRadius(getEffectRadius() + 3, host.posX, host.posY, host.posZ, host.world, Entity.class);
targetsBeyondRange.removeAll(targetsInRange);
targetsBeyondRange.forEach(e -> e.updateBlocked = false);
}
@SubscribeEvent
public static void onLivingUpdateEvent(LivingUpdateEvent event){
EntityLivingBase entity = event.getEntityLiving();
if(entity.isPotionActive(WizardryPotions.slow_time)){
performEffectConsistent(entity, entity.getActivePotionEffect(WizardryPotions.slow_time).getAmplifier());
}
}
@SubscribeEvent
public static void onPotionAddedEvent(PotionEvent.PotionAddedEvent event){
if(event.getEntity().world.isRemote && event.getPotionEffect().getPotion() == WizardryPotions.slow_time
&& event.getEntity() == net.minecraft.client.Minecraft.getMinecraft().player){
if(Wizardry.settings.useShaders) net.minecraft.client.Minecraft.getMinecraft().entityRenderer.loadShader(SlowTime.SHADER);
electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect();
}
}
@SubscribeEvent
public static void onPotionExpiryEvent(PotionEvent.PotionExpiryEvent event){
if(event.getPotionEffect() != null && event.getPotionEffect().getPotion() == WizardryPotions.slow_time){
unblockNearbyEntities(event.getEntityLiving());
if(!event.getEntity().world.isRemote){
WizardryPacketHandler.net.sendToDimension(new PacketEndSlowTime.Message(event.getEntityLiving()), event.getEntity().dimension);
}
}
}
@SubscribeEvent
public static void onPotionRemoveEvent(PotionEvent.PotionRemoveEvent event){
if(event.getPotionEffect() != null && event.getPotionEffect().getPotion() == WizardryPotions.slow_time){
unblockNearbyEntities(event.getEntityLiving());
if(!event.getEntity().world.isRemote){
WizardryPacketHandler.net.sendToDimension(new PacketEndSlowTime.Message(event.getEntityLiving()), event.getEntity().dimension);
}
}
}
}