This commit is contained in:
IzzelAliz 2020-06-14 14:49:42 +08:00
parent 792df330b4
commit 4f0e52fb69
70 changed files with 2573 additions and 771 deletions

View File

@ -52,4 +52,6 @@ public interface EntityBridge extends ICommandSourceBridge {
void bridge$setRideCooldown(int rideCooldown);
int bridge$getRideCooldown();
double bridge$getEyeHeight();
}

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.common.bridge.entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectInstance;
import org.bukkit.craftbukkit.v.entity.CraftLivingEntity;
@ -18,6 +19,12 @@ public interface LivingEntityBridge extends EntityBridge {
void bridge$setExpToDrop(int amount);
int bridge$getExpToDrop();
void bridge$dropExperience();
void bridge$createWitherRose(LivingEntity entity);
void bridge$pushHealReason(EntityRegainHealthEvent.RegainReason regainReason);
void bridge$heal(float healAmount, EntityRegainHealthEvent.RegainReason regainReason);

View File

@ -16,6 +16,8 @@ public interface MobEntityBridge extends LivingEntityBridge {
void bridge$setPersistenceRequired(boolean value);
void bridge$setAware(boolean aware);
interface Hack {
ResourceLocation getLootTable();

View File

@ -1,11 +1,11 @@
package io.izzel.arclight.common.bridge.entity.player;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
public interface PlayerEntityBridge extends LivingEntityBridge {
@ -13,6 +13,8 @@ public interface PlayerEntityBridge extends LivingEntityBridge {
String bridge$getSpawnWorld();
void bridge$setSpawnWorld(String world);
@Override
CraftHumanEntity bridge$getBukkitEntity();

View File

@ -9,6 +9,8 @@ import org.bukkit.Location;
import org.bukkit.craftbukkit.v.entity.CraftPlayer;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.Optional;
public interface ServerPlayerEntityBridge extends PlayerEntityBridge {
@Override
@ -16,6 +18,8 @@ public interface ServerPlayerEntityBridge extends PlayerEntityBridge {
void bridge$pushChangeDimensionCause(PlayerTeleportEvent.TeleportCause cause);
Optional<PlayerTeleportEvent.TeleportCause> bridge$getTeleportCause();
BlockPos bridge$getSpawnPoint(ServerWorld world);
boolean bridge$isMovementBlocked();

View File

@ -0,0 +1,11 @@
package io.izzel.arclight.common.bridge.entity.projectile;
import net.minecraft.item.Item;
public interface ProjectileItemEntityBridge {
interface Hack {
Item getDefaultItem();
}
}

View File

@ -14,4 +14,6 @@ public interface ExplosionBridge {
Explosion.Mode bridge$getMode();
boolean bridge$wasCancelled();
float bridge$callBlockExplodeEvent();
}

View File

@ -0,0 +1,12 @@
package io.izzel.arclight.common.bridge.world;
import net.minecraft.block.pattern.BlockPattern;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
public interface TeleporterBridge {
boolean bridge$makePortal(Entity entityIn, BlockPos pos, int createRadius);
BlockPattern.PortalInfo bridge$placeInPortal(Entity p_222268_1_, BlockPos pos, float p_222268_2_, int searchRadius, boolean searchOnly);
}

View File

@ -0,0 +1,8 @@
package io.izzel.arclight.common.bridge.world.dimension;
import net.minecraft.world.dimension.DimensionType;
public interface DimensionTypeBridge {
DimensionType bridge$getType();
}

View File

@ -169,6 +169,13 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge,
@Shadow public abstract float getEyeHeight();
@Shadow @Nullable public abstract Entity changeDimension(DimensionType destination);
@Shadow public abstract boolean isRidingSameEntity(Entity entityIn);
@Shadow public boolean noClip;
@Shadow public abstract double getPosX();
@Shadow public abstract double getPosY();
@Shadow public abstract double getPosZ();
@Shadow(remap = false) public abstract void revive();
@Shadow public abstract Vec3d getPositionVec();
@Shadow public abstract boolean isInvulnerable();
// @formatter:on
private static final int CURRENT_LEVEL = 2;

View File

@ -1,9 +1,6 @@
package io.izzel.arclight.common.mixin.core.entity;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
@ -15,7 +12,6 @@ import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AbstractAttributeMap;
import net.minecraft.entity.ai.attributes.IAttribute;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.item.ExperienceOrbEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.passive.AnimalEntity;
import net.minecraft.entity.passive.TameableEntity;
@ -29,7 +25,6 @@ import net.minecraft.nbt.FloatNBT;
import net.minecraft.nbt.INBT;
import net.minecraft.nbt.IntNBT;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
@ -39,13 +34,12 @@ import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSource;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.entity.living.PotionEvent;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.attribute.CraftAttributeMap;
@ -73,10 +67,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
@ -99,18 +89,9 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
@Shadow protected boolean dead;
@Shadow public void remove(boolean keepData) { }
@Shadow public abstract IAttributeInstance getAttribute(IAttribute attribute);
@Shadow @Final public Map<Effect, EffectInstance> activePotionsMap;
@Shadow protected abstract void onFinishedPotionEffect(EffectInstance effect);
@Shadow protected abstract void onChangedPotionEffect(EffectInstance id, boolean reapply);
@Shadow public boolean potionsNeedUpdate;
@Shadow protected abstract void updatePotionMetadata();
@Shadow @Final private static DataParameter<Integer> POTION_EFFECTS;
@Shadow @Final private static DataParameter<Boolean> HIDE_PARTICLES;
@Shadow public abstract boolean removePotionEffect(Effect effectIn);
@Shadow public abstract boolean isPotionApplicable(EffectInstance potioneffectIn);
@Shadow protected abstract void onNewPotionEffect(EffectInstance id);
@Shadow public abstract boolean clearActivePotions();
@Shadow @Nullable public abstract EffectInstance removeActivePotionEffect(@Nullable Effect potioneffectin);
@Shadow @Final public static DataParameter<Float> HEALTH;
@Shadow public abstract boolean isPotionActive(Effect potionIn);
@Shadow public abstract boolean isSleeping();
@ -162,6 +143,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
@Shadow public CombatTracker combatTracker;
@Shadow public abstract ItemStack getHeldItemOffhand();
@Shadow public abstract Random getRNG();
@Shadow public abstract Optional<BlockPos> getBedPosition();
@Shadow public abstract boolean addPotionEffect(EffectInstance effectInstanceIn);
// @formatter:on
public int expToDrop;
@ -198,8 +181,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
public int getExpReward() {
int exp = this.getExperiencePoints(this.attackingPlayer);
if (!this.world.isRemote && (this.recentlyHit > 0 || this.isPlayer()) && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) {
int exp = this.getExperiencePoints(this.attackingPlayer);
return ForgeEventFactory.getExperienceDrop((LivingEntity) (Object) this, this.attackingPlayer, exp);
} else {
return 0;
@ -216,40 +199,16 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
this.expToDrop = amount;
}
@Override
public int bridge$getExpToDrop() {
return this.expToDrop;
}
@Override
public boolean bridge$isForceDrops() {
return forceDrops;
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void onDeathUpdate() {
++this.deathTime;
if (this.deathTime >= 20 && !this.removed) {
if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT))) {
int i = this.expToDrop;
while (i > 0) {
int j = ExperienceOrbEntity.getXPSplit(i);
i -= j;
this.world.addEntity(new ExperienceOrbEntity(this.world, this.posX, this.posY, this.posZ, j));
}
this.expToDrop = 0;
}
this.remove((Object) this instanceof ServerPlayerEntity); //Forge keep data until we revive player
for (int k = 0; k < 20; ++k) {
double d2 = this.rand.nextGaussian() * 0.02D;
double d0 = this.rand.nextGaussian() * 0.02D;
double d1 = this.rand.nextGaussian() * 0.02D;
this.world.addParticle(ParticleTypes.POOF, this.posX + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), this.posY + (double) (this.rand.nextFloat() * this.getHeight()), this.posZ + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), d2, d0, d1);
}
}
}
@Inject(method = "readAdditional", at = @At("HEAD"))
public void arclight$readMaxHealth(CompoundNBT compound, CallbackInfo ci) {
if (compound.contains("Bukkit.MaxHealth")) {
@ -262,160 +221,11 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
}
private boolean isTickingEffects = false;
private List<Map.Entry<Either<EffectInstance, Effect>, EntityPotionEffectEvent.Cause>> effectsToProcess = Lists.newArrayList();
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void updatePotionEffects() {
this.isTickingEffects = true;
Iterator<Effect> iterator = this.activePotionsMap.keySet().iterator();
try {
while (iterator.hasNext()) {
Effect effect = iterator.next();
EffectInstance effectinstance = this.activePotionsMap.get(effect);
if (!effectinstance.tick((LivingEntity) (Object) this)) {
if (!this.world.isRemote && !MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionExpiryEvent((LivingEntity) (Object) this, effectinstance))) {
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION);
if (event.isCancelled()) {
continue;
}
iterator.remove();
this.onFinishedPotionEffect(effectinstance);
}
} else if (effectinstance.getDuration() % 600 == 0) {
this.onChangedPotionEffect(effectinstance, false);
}
}
} catch (ConcurrentModificationException ignored) {
}
isTickingEffects = false;
for (Map.Entry<Either<EffectInstance, Effect>, EntityPotionEffectEvent.Cause> e : effectsToProcess) {
Either<EffectInstance, Effect> either = e.getKey();
EntityPotionEffectEvent.Cause cause = e.getValue();
bridge$pushEffectCause(cause);
if (either.left().isPresent()) {
addPotionEffect(either.left().get());
} else {
removePotionEffect(either.right().get());
}
}
effectsToProcess.clear();
if (this.potionsNeedUpdate) {
if (!this.world.isRemote) {
this.updatePotionMetadata();
}
this.potionsNeedUpdate = false;
}
int i = this.dataManager.get(POTION_EFFECTS);
boolean flag1 = this.dataManager.get(HIDE_PARTICLES);
if (i > 0) {
boolean flag;
if (this.isInvisible()) {
flag = this.rand.nextInt(15) == 0;
} else {
flag = this.rand.nextBoolean();
}
if (flag1) {
flag &= this.rand.nextInt(5) == 0;
}
if (flag && i > 0) {
double d0 = (double) (i >> 16 & 255) / 255.0D;
double d1 = (double) (i >> 8 & 255) / 255.0D;
double d2 = (double) (i >> 0 & 255) / 255.0D;
this.world.addParticle(flag1 ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, this.posX + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), this.posY + this.rand.nextDouble() * (double) this.getHeight(), this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), d0, d1, d2);
}
}
}
@Inject(method = "clearActivePotions", at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraftforge/eventbus/api/IEventBus;post(Lnet/minecraftforge/eventbus/api/Event;)Z"))
public void arclight$clearReason(CallbackInfoReturnable<Boolean> cir) {
arclight$action = EntityPotionEffectEvent.Action.CLEARED;
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public boolean addPotionEffect(EffectInstance effectInstanceIn) {
EntityPotionEffectEvent.Cause cause = arclight$cause == null ? EntityPotionEffectEvent.Cause.UNKNOWN : arclight$cause;
arclight$cause = null;
if (isTickingEffects) {
effectsToProcess.add(Maps.immutableEntry(Either.left(effectInstanceIn), cause));
return true;
}
if (!this.isPotionApplicable(effectInstanceIn)) {
return false;
} else {
EffectInstance effectinstance = this.activePotionsMap.get(effectInstanceIn.getPotion());
boolean override = false;
if (effectinstance != null) {
override = new EffectInstance(effectinstance).combine(effectInstanceIn);
}
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn, cause, override);
if (event.isCancelled()) {
return false;
}
MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionAddedEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn));
if (effectinstance == null) {
this.activePotionsMap.put(effectInstanceIn.getPotion(), effectInstanceIn);
this.onNewPotionEffect(effectInstanceIn);
return true;
} else if (event.isOverride()) {
effectinstance.combine(effectInstanceIn);
this.onChangedPotionEffect(effectinstance, true);
return true;
} else {
return false;
}
}
}
@SuppressWarnings("unused") // mock
public EffectInstance c(@Nullable Effect potioneffectin, EntityPotionEffectEvent.Cause cause) {
bridge$pushEffectCause(cause);
return removeActivePotionEffect(potioneffectin);
}
@Inject(method = "removeActivePotionEffect", at = @At("HEAD"))
public void arclight$clearActive(Effect effect, CallbackInfoReturnable<EffectInstance> cir) {
EntityPotionEffectEvent.Cause cause = arclight$cause == null ? EntityPotionEffectEvent.Cause.UNKNOWN : arclight$cause;
arclight$cause = null;
if (isTickingEffects) {
effectsToProcess.add(Maps.immutableEntry(Either.right(effect), cause));
cir.setReturnValue(null);
return;
}
EffectInstance effectInstance = this.activePotionsMap.get(effect);
if (effectInstance == null) {
cir.setReturnValue(null);
return;
}
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectInstance, null, cause);
if (event.isCancelled()) {
cir.setReturnValue(null);
}
}
private transient EntityPotionEffectEvent.Action arclight$action;
@Override
@ -669,6 +479,11 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
float absorptionModifier = absorption.apply((double) f).floatValue();
EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent((LivingEntity) (Object) this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption);
if (damagesource.getTrueSource() instanceof PlayerEntity) {
((PlayerEntity) damagesource.getTrueSource()).resetCooldown();
}
if (event.isCancelled()) {
return false;
}
@ -877,20 +692,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt
}
}
private transient boolean arclight$fallSuccess;
@Inject(method = "fall", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z"))
public void arclight$fall(float distance, float damageMultiplier, CallbackInfo ci) {
if (!arclight$fallSuccess) {
ci.cancel();
}
}
@Redirect(method = "fall", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z"))
public boolean arclight$fall(LivingEntity livingEntity, DamageSource source, float amount) {
return arclight$fallSuccess = livingEntity.attackEntityFrom(source, amount);
}
@Redirect(method = "applyArmorCalculations", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;damageArmor(F)V"))
public void arclight$muteDamageArmor(LivingEntity livingEntity, float damage) {
}

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.entity;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.entity.MobEntityBridge;
import io.izzel.arclight.common.mod.ArclightMod;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
@ -37,7 +38,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import io.izzel.arclight.common.mod.ArclightMod;
import javax.annotation.Nullable;
import java.util.concurrent.atomic.AtomicBoolean;
@ -66,6 +66,13 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt
@Shadow public abstract boolean isAIDisabled();
// @formatter:on
public boolean aware;
@Override
public void bridge$setAware(boolean aware) {
this.aware = aware;
}
@Inject(method = "setCanPickUpLoot", at = @At("HEAD"))
public void arclight$setPickupLoot(boolean canPickup, CallbackInfo ci) {
super.canPickUpLoot = canPickup;
@ -83,6 +90,7 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt
@Inject(method = "<init>", at = @At("RETURN"))
private void arclight$init(EntityType<? extends MobEntity> type, World worldIn, CallbackInfo ci) {
this.persistenceRequired = !this.canDespawn(0.0);
this.aware = true;
}
private transient AtomicBoolean arclight$targetSuccess;
@ -155,6 +163,18 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt
arclight$fireEvent = fireEvent;
}
@Inject(method = "writeAdditional", at = @At("HEAD"))
private void arclight$setAware(CompoundNBT compound, CallbackInfo ci) {
compound.putBoolean("Bukkit.Aware", this.aware);
}
@Inject(method = "readAdditional", at = @At("HEAD"))
private void arclight$readAware(CompoundNBT compound, CallbackInfo ci) {
if (compound.contains("Bukkit.Aware")) {
this.aware = compound.getBoolean("Bukkit.Aware");
}
}
@Redirect(method = "readAdditional", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/MobEntity;setCanPickUpLoot(Z)V"))
public void arclight$setIfTrue(MobEntity mobEntity, boolean canPickup) {
if (canPickup) mobEntity.setCanPickUpLoot(true);
@ -165,6 +185,14 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt
return nbt.getBoolean(key) || this.persistenceRequired;
}
@Inject(method = "updateEntityActionState", cancellable = true, at = @At("HEAD"))
private void arclight$unaware(CallbackInfo ci) {
if (!this.aware) {
++this.idleTime;
ci.cancel();
}
}
/**
* @author IzzelAliz
* @reason

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.entity.item;
import com.google.common.base.Preconditions;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.PlayerInventoryBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.network.datasync.EntityDataManagerBridge;
import io.izzel.arclight.common.mixin.core.entity.EntityMixin;
@ -23,10 +24,8 @@ import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import io.izzel.arclight.common.bridge.entity.player.PlayerInventoryBridge;
import java.util.UUID;
@ -38,7 +37,6 @@ public abstract class ItemEntityMixin extends EntityMixin {
@Shadow public int pickupDelay;
@Shadow public abstract ItemStack getItem();
@Shadow private UUID owner;
@Shadow public int age;
// @formatter:on
@Inject(method = "func_213858_a", cancellable = true, at = @At("HEAD"))
@ -48,13 +46,6 @@ public abstract class ItemEntityMixin extends EntityMixin {
}
}
@Redirect(method = "func_213858_a", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/entity/item/ItemEntity;setItem(Lnet/minecraft/item/ItemStack;)V"))
private static void arclight$setNonEmpty(ItemEntity itemEntity, ItemStack stack) {
if (!stack.isEmpty()) {
itemEntity.setItem(stack);
}
}
@Inject(method = "attackEntityFrom", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/item/ItemEntity;markVelocityChanged()V"))
private void arclight$damageNonLiving(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
if (CraftEventFactory.handleNonLivingEntityDamageEvent((ItemEntity) (Object) this, source, amount)) {
@ -109,7 +100,7 @@ public abstract class ItemEntityMixin extends EntityMixin {
} else if (this.pickupDelay == 0) {
this.pickupDelay = -1;
}
if (this.pickupDelay == 0 && (this.owner == null || 6000 - this.age <= 200 || this.owner.equals(entity.getUniqueID())) && entity.inventory.addItemStackToInventory(itemstack)) {
if (this.pickupDelay == 0 && (this.owner == null /*|| 6000 - this.age <= 200*/ || this.owner.equals(entity.getUniqueID())) && entity.inventory.addItemStackToInventory(itemstack)) {
entity.onItemPickup((ItemEntity) (Object) this, i);
if (itemstack.isEmpty()) {
this.remove();

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.common.mixin.core.entity.item;
import io.izzel.arclight.api.ArclightVersion;
import io.izzel.arclight.common.mixin.core.entity.EntityMixin;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
@ -44,9 +45,11 @@ public abstract class TNTEntityMixin extends EntityMixin {
*/
@Overwrite
public void tick() {
if (ArclightVersion.lesserThan(ArclightVersion.v1_15)) {
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
}
if (!this.hasNoGravity()) {
this.setMotion(this.getMotion().add(0.0D, -0.04D, 0.0D));
}
@ -65,9 +68,11 @@ public abstract class TNTEntityMixin extends EntityMixin {
this.remove();
} else {
this.handleWaterMovement();
if (this.world.isRemote) {
this.world.addParticle(ParticleTypes.SMOKE, this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D);
}
}
}
/**
* @author IzzelAliz

View File

@ -160,9 +160,11 @@ public abstract class AbstractMinecartEntityMixin extends EntityMixin {
this.setRotation(this.rotationYaw, this.rotationPitch);
}
} else {
/*
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
*/
if (!this.hasNoGravity()) {
this.setMotion(this.getMotion().add(0.0, -0.04, 0.0));
}
@ -217,12 +219,15 @@ public abstract class AbstractMinecartEntityMixin extends EntityMixin {
entity.startRiding((AbstractMinecartEntity) (Object) this);
}
} else {
if (!isRidingSameEntity(entity)) {
VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, ((EntityBridge) entity).bridge$getBukkitEntity());
Bukkit.getPluginManager().callEvent(collisionEvent);
if (!collisionEvent.isCancelled()) {
entity.applyEntityCollision((AbstractMinecartEntity) (Object) this);
if (collisionEvent.isCancelled()) {
continue;
}
}
entity.applyEntityCollision((AbstractMinecartEntity) (Object) this);
}
}
}
} else {
@ -273,14 +278,16 @@ public abstract class AbstractMinecartEntityMixin extends EntityMixin {
return this.isBeingRidden() || !this.slowWhenEmpty;
}
@Inject(method = "applyEntityCollision", at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/entity/Entity;posX:D"))
@Inject(method = "applyEntityCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/item/minecart/AbstractMinecartEntity;isPassenger(Lnet/minecraft/entity/Entity;)Z"))
private void arclight$vehicleCollide(Entity entityIn, CallbackInfo ci) {
if (!this.isPassenger(entityIn)) {
VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), ((EntityBridge) entityIn).bridge$getBukkitEntity());
Bukkit.getPluginManager().callEvent(collisionEvent);
if (collisionEvent.isCancelled()) {
ci.cancel();
}
}
}
public Vector getFlyingVelocityMod() {
return new Vector(flyingX, flyingY, flyingZ);

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.common.mixin.core.entity.monster;
import io.izzel.arclight.api.ArclightVersion;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -46,7 +47,11 @@ public abstract class SilverfishEntity_SummonSilverfishGoalMixin extends Goal {
continue;
}
if (ForgeEventFactory.getMobGriefingEvent(world, this.silverfish)) {
if (ArclightVersion.atLeast(ArclightVersion.v1_15)) {
world.destroyBlock(blockpos1, true, this.silverfish);
} else {
world.destroyBlock(blockpos1, true);
}
} else {
world.setBlockState(blockpos1, ((SilverfishBlock) block).getMimickedBlock().getDefaultState(), 3);
}

View File

@ -55,6 +55,7 @@ public abstract class SlimeEntityMixin extends MobEntityMixin {
if (this.isNoDespawnRequired()) {
entityslime.enablePersistence();
}
entityslime.setInvulnerable(this.isInvulnerable());
entityslime.setSlimeSize(i / 2, true);
entityslime.setLocationAndAngles(this.posX + f, this.posY + 0.5, this.posZ + f2, this.rand.nextFloat() * 360.0f, 0.0f);
slimes.add(entityslime);

View File

@ -33,11 +33,11 @@ public abstract class ZombieVillagerEntityMixin extends ZombieEntityMixin {
bridge$pushEffectCause(EntityPotionEffectEvent.Cause.CONVERSION);
}
@Redirect(method = "func_213791_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombieVillagerEntity;remove()V"))
@Redirect(method = "cureZombie", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombieVillagerEntity;remove()V"))
private void arclight$transformPre(ZombieVillagerEntity zombieVillagerEntity) {
}
@Inject(method = "func_213791_a", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z"))
@Inject(method = "cureZombie", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z"))
private void arclight$transform(ServerWorld world, CallbackInfo ci, VillagerEntity villagerEntity) {
if (CraftEventFactory.callEntityTransformEvent((ZombieVillagerEntity)(Object)this, villagerEntity, EntityTransformEvent.TransformReason.CURED).isCancelled()) {
((ZombieVillager) getBukkitEntity()).setConversionTime(-1);

View File

@ -1,14 +1,9 @@
package io.izzel.arclight.common.mixin.core.entity.passive;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.entity.passive.OcelotEntity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(OcelotEntity.class)
public abstract class OcelotEntityMixin extends AnimalEntityMixin {
@ -27,9 +22,4 @@ public abstract class OcelotEntityMixin extends AnimalEntityMixin {
public boolean canDespawn(double distanceToClosestPlayer) {
return !this.isTrusting() /*&& this.ticksExisted > 2400*/;
}
@Inject(method = "func_213525_dW", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z"))
private void arclight$spawnBaby(CallbackInfo ci) {
((WorldBridge) this.world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.OCELOT_BABY);
}
}

View File

@ -15,7 +15,7 @@ import java.util.function.Predicate;
@Mixin(PandaEntity.class)
public abstract class PandaEntityMixin extends AnimalEntityMixin {
@Shadow @Final private static Predicate<ItemEntity> field_213607_bQ;
@Shadow @Final private static Predicate<ItemEntity> PANDA_ITEMS;
/**
* @author IzzelAliz
@ -23,7 +23,7 @@ public abstract class PandaEntityMixin extends AnimalEntityMixin {
*/
@Overwrite
protected void updateEquipmentIfNeeded(ItemEntity itemEntity) {
boolean cancel = this.getItemStackFromSlot(EquipmentSlotType.MAINHAND).isEmpty() && field_213607_bQ.test(itemEntity);
boolean cancel = this.getItemStackFromSlot(EquipmentSlotType.MAINHAND).isEmpty() && PANDA_ITEMS.test(itemEntity);
if (CraftEventFactory.callEntityPickupItemEvent((PandaEntity) (Object) this, itemEntity, 0, cancel).isCancelled()) {
ItemStack itemstack = itemEntity.getItem();
this.setItemStackToSlot(EquipmentSlotType.MAINHAND, itemstack);

View File

@ -37,7 +37,7 @@ public abstract class SheepEntityMixin extends AnimalEntityMixin {
}
}
@Inject(method = "func_213611_a", locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN"))
@Inject(method = "createDyeColorCraftingInventory", locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN"))
private static void arclight$resultInv(DyeColor p_213611_0_, DyeColor p_213611_1_, CallbackInfoReturnable<CraftingInventory> cir, CraftingInventory craftingInventory) {
((CraftingInventoryBridge) craftingInventory).bridge$setResultInventory(new CraftResultInventory());
}

View File

@ -19,11 +19,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(WolfEntity.class)
public abstract class WolfEntityMixin extends TameableEntityMixin {
@Shadow
public abstract void setAngry(boolean angry);
@Shadow
public abstract boolean isAngry();
// @formatter:off
@Shadow public abstract void setAngry(boolean angry);
@Shadow public abstract boolean isAngry();
// @formatter:on
@Override
public boolean setGoalTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fire) {
@ -54,6 +53,11 @@ public abstract class WolfEntityMixin extends TameableEntityMixin {
private void arclight$handledBy(SitGoal sitGoal, boolean sitting) {
}
@Redirect(method = "setTamed", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/WolfEntity;setHealth(F)V"))
private void arclight$healToMax(WolfEntity wolfEntity, float health) {
wolfEntity.setHealth(wolfEntity.getMaxHealth());
}
@Inject(method = "processInteract", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/WolfEntity;heal(F)V"))
private void arclight$healReason(PlayerEntity player, Hand hand, CallbackInfoReturnable<Boolean> cir) {
bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.EATING);

View File

@ -1,14 +1,15 @@
package io.izzel.arclight.common.mixin.core.entity.player;
import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.entity.InternalEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.inventory.IInventoryBridge;
import io.izzel.arclight.common.bridge.util.DamageSourceBridge;
import io.izzel.arclight.common.bridge.util.FoodStatsBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge;
import io.izzel.arclight.common.mixin.core.entity.LivingEntityMixin;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.CreatureAttribute;
import net.minecraft.entity.Entity;
@ -23,6 +24,7 @@ import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.EnderChestInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.PlayerContainer;
import net.minecraft.item.ItemStack;
@ -35,14 +37,12 @@ import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.stats.Stat;
import net.minecraft.stats.Stats;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.FoodStats;
import net.minecraft.util.Hand;
import net.minecraft.util.HandSide;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -53,18 +53,16 @@ import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.ForgeHooks;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.util.CraftVector;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityCombustByEntityEvent;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.player.PlayerBedLeaveEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerVelocityEvent;
import org.bukkit.scoreboard.Team;
@ -75,25 +73,18 @@ import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import io.izzel.arclight.common.bridge.util.DamageSourceBridge;
import io.izzel.arclight.common.mixin.core.entity.LivingEntityMixin;
import java.util.List;
import java.util.Optional;
@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin extends LivingEntityMixin implements PlayerEntityBridge {
// @formatter:off
@Shadow public int sleepTimer;
@Shadow public abstract String getScoreboardName();
@Shadow public abstract Either<PlayerEntity.SleepResult, Unit> trySleep(BlockPos at);
@Shadow public abstract void startSleeping(BlockPos p_213342_1_);
@Shadow @Final public PlayerAbilities abilities;
@Shadow public abstract float getCooledAttackStrength(float adjustTicks);
@Shadow public abstract void resetCooldown();
@ -104,7 +95,7 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla
@Shadow public abstract void onEnchantmentCritical(Entity entityHit);
@Shadow public abstract void addStat(ResourceLocation p_195067_1_, int p_195067_2_);
@Shadow public abstract void addExhaustion(float exhaustion);
@Shadow private long field_223730_e;
@Shadow private long timeEntitySatOnShoulder;
@Shadow public abstract void setRightShoulderEntity(CompoundNBT tag);
@Shadow public abstract void setLeftShoulderEntity(CompoundNBT tag);
@Shadow public abstract CompoundNBT getRightShoulderEntity();
@ -123,6 +114,7 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla
@Shadow protected FoodStats foodStats;
@Shadow protected boolean isMovementBlocked() { return false; }
@Shadow public abstract Scoreboard getWorldScoreboard();
@Shadow protected EnderChestInventory enterChestInventory;
// @formatter:on
public boolean fauxSleeping;
@ -133,6 +125,7 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla
private void arclight$init(World worldIn, GameProfile gameProfileIn, CallbackInfo ci) {
oldLevel = -1;
((FoodStatsBridge) this.foodStats).bridge$setEntityHuman((PlayerEntity) (Object) this);
((IInventoryBridge) this.enterChestInventory).setOwner(((HumanEntity) this.getBukkitEntity()));
}
@Override
@ -422,92 +415,9 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla
}
}
private boolean arclight$forceSleep = false;
private Object arclight$processSleep = null;
public CraftHumanEntity getBukkitEntity() {
return (CraftHumanEntity) ((InternalEntityBridge) this).internal$getBukkitEntity();
}
private Either<PlayerEntity.SleepResult, Unit> getBedResult(BlockPos at, Direction direction) {
arclight$processSleep = true;
Either<PlayerEntity.SleepResult, Unit> either = this.trySleep(at);
arclight$processSleep = null;
return either;
}
public Either<PlayerEntity.SleepResult, Unit> sleep(BlockPos at, boolean force) {
arclight$forceSleep = force;
try {
return this.trySleep(at);
} finally {
arclight$forceSleep = false;
}
}
@Inject(method = "trySleep", cancellable = true, at = @At(value = "HEAD"))
public void arclight$onSleep(BlockPos at, CallbackInfoReturnable<Either<PlayerEntity.SleepResult, Unit>> cir) {
if (arclight$processSleep == null) {
Either<PlayerEntity.SleepResult, Unit> result = getBedResult(at, null);
if (result.left().orElse(null) == PlayerEntity.SleepResult.OTHER_PROBLEM) {
cir.setReturnValue(result);
return;
}
if (arclight$forceSleep) {
result = Either.right(Unit.INSTANCE);
}
if (this.bridge$getBukkitEntity() instanceof Player) {
result = CraftEventFactory.callPlayerBedEnterEvent((PlayerEntity) (Object) this, at, result);
if (result.left().isPresent()) {
cir.setReturnValue(result);
return;
}
}
this.startSleeping(at);
this.sleepTimer = 0;
if (this.world instanceof ServerWorld) {
((ServerWorld) this.world).updateAllPlayersSleepingFlag();
}
cir.setReturnValue(Either.right(Unit.INSTANCE));
}
}
@Inject(method = "trySleep", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;startSleeping(Lnet/minecraft/util/math/BlockPos;)V"))
public void arclight$preSleep(BlockPos at, CallbackInfoReturnable<Either<PlayerEntity.SleepResult, Unit>> cir) {
if (arclight$processSleep != null) {
cir.setReturnValue(Either.right(Unit.INSTANCE));
}
}
@Inject(method = "wakeUpPlayer", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I"))
private void arclight$wakeup(boolean immediately, boolean updateWorldFlag, boolean setSpawn, CallbackInfo ci, Optional<BlockPos> optional) {
if (this.getBukkitEntity() instanceof Player) {
final Player player = (Player) this.getBukkitEntity();
final BlockPos blockposition2 = optional.orElse(null);
Block bed;
if (blockposition2 != null) {
bed = CraftBlock.at(this.world, blockposition2);
} else {
bed = ((WorldBridge) this.world).bridge$getWorld().getBlockAt(player.getLocation());
}
final PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, setSpawn);
Bukkit.getPluginManager().callEvent(event);
arclight$setSpawn = event.shouldSetSpawnLocation();
}
}
private boolean arclight$setSpawn;
@ModifyVariable(method = "wakeUpPlayer", index = 3, name = "setSpawn", at = @At(value = "FIELD", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I"))
private boolean arclight$modifySpawn(boolean setSpawn) {
return arclight$setSpawn;
}
@Inject(method = "setSpawnPoint(Lnet/minecraft/util/math/BlockPos;Z)V", at = @At("RETURN"))
private void arclight$updateSpawnpoint(BlockPos pos, boolean forced, CallbackInfo ci) {
this.spawnWorld = pos == null ? "" : this.world.worldInfo.getWorldName();
@Override
public void bridge$setSpawnWorld(String world) {
this.spawnWorld = world;
}
@Redirect(method = "travel", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;setFlag(IZ)V"))
@ -523,7 +433,7 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla
*/
@Overwrite
protected void spawnShoulderEntities() {
if (this.field_223730_e + 20L < this.world.getGameTime()) {
if (this.timeEntitySatOnShoulder + 20L < this.world.getGameTime()) {
if (this.spawnEntityFromShoulder(this.getLeftShoulderEntity())) {
this.setLeftShoulderEntity(new CompoundNBT());
}
@ -548,11 +458,6 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla
return (CraftHumanEntity) ((InternalEntityBridge) this).internal$getBukkitEntity();
}
@Override
public Either<PlayerEntity.SleepResult, Unit> bridge$trySleep(BlockPos at, boolean force) {
return sleep(at, force);
}
@Override
public String bridge$getSpawnWorld() {
return spawnWorld;

View File

@ -1,7 +1,6 @@
package io.izzel.arclight.common.mixin.core.entity.player;
import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.entity.InternalEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
@ -9,12 +8,8 @@ import io.izzel.arclight.common.bridge.inventory.container.ContainerBridge;
import io.izzel.arclight.common.bridge.util.FoodStatsBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.mod.util.ChestBlockDoubleInventoryHacks;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.boss.WitherEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.passive.horse.AbstractHorseEntity;
import net.minecraft.entity.player.PlayerEntity;
@ -24,7 +19,6 @@ import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.HorseInventoryContainer;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.item.crafting.RecipeBook;
import net.minecraft.item.crafting.ServerRecipeBook;
import net.minecraft.nbt.CompoundNBT;
@ -33,21 +27,14 @@ import net.minecraft.network.play.client.CClientSettingsPacket;
import net.minecraft.network.play.server.SChangeGameStatePacket;
import net.minecraft.network.play.server.SCombatPacket;
import net.minecraft.network.play.server.SOpenHorseWindowPacket;
import net.minecraft.network.play.server.SPlayEntityEffectPacket;
import net.minecraft.network.play.server.SPlaySoundEventPacket;
import net.minecraft.network.play.server.SPlayerAbilitiesPacket;
import net.minecraft.network.play.server.SRespawnPacket;
import net.minecraft.network.play.server.SServerDifficultyPacket;
import net.minecraft.network.play.server.SSetSlotPacket;
import net.minecraft.network.play.server.SUpdateHealthPacket;
import net.minecraft.potion.EffectInstance;
import net.minecraft.scoreboard.Score;
import net.minecraft.scoreboard.ScoreCriteria;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.scoreboard.Team;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.management.PlayerInteractionManager;
import net.minecraft.server.management.PlayerList;
import net.minecraft.stats.Stat;
import net.minecraft.stats.Stats;
import net.minecraft.util.CombatTracker;
@ -55,7 +42,6 @@ import net.minecraft.util.DamageSource;
import net.minecraft.util.FoodStats;
import net.minecraft.util.HandSide;
import net.minecraft.util.NonNullList;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -67,9 +53,7 @@ import net.minecraft.util.text.event.HoverEvent;
import net.minecraft.world.GameRules;
import net.minecraft.world.GameType;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.WorldInfo;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
@ -80,18 +64,14 @@ import org.bukkit.craftbukkit.v.entity.CraftPlayer;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v.scoreboard.CraftScoreboardManager;
import org.bukkit.craftbukkit.v.util.BlockStateListPopulator;
import org.bukkit.craftbukkit.v.util.CraftChatMessage;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerChangedMainHandEvent;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerLocaleChangeEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.world.PortalCreateEvent;
import org.bukkit.inventory.MainHand;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@ -108,6 +88,7 @@ import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Random;
import java.util.function.Consumer;
@ -125,11 +106,11 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
@Shadow public abstract void closeScreen();
@Shadow public abstract void setSpectatingEntity(Entity entityToSpectate);
@Shadow public boolean invulnerableDimensionChange;
@Shadow public abstract ServerWorld func_71121_q();
@Shadow public abstract ServerWorld getServerWorld();
@Shadow public boolean queuedEndExit;
@Shadow private boolean seenCredits;
@Shadow @Nullable private Vec3d enteredNetherPosition;
@Shadow protected abstract void func_213846_b(ServerWorld p_213846_1_);
@Shadow public abstract void func_213846_b(ServerWorld p_213846_1_);
@Shadow public int lastExperience;
@Shadow private float lastHealth;
@Shadow private int lastFoodLevel;
@ -137,7 +118,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
@Shadow public abstract void getNextWindowId();
@Shadow public abstract void sendMessage(ITextComponent component);
@Shadow public String language;
@Shadow public abstract void func_200619_a(ServerWorld p_200619_1_, double x, double y, double z, float yaw, float pitch);
@Shadow public abstract void teleport(ServerWorld p_200619_1_, double x, double y, double z, float yaw, float pitch);
@Shadow public abstract void giveExperiencePoints(int p_195068_1_);
// @formatter:on
@ -168,7 +149,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
public BlockPos getSpawnPoint(ServerWorld worldserver) {
BlockPos blockposition = worldserver.getSpawnPoint();
if (worldserver.dimension.hasSkyLight() && worldserver.getWorldInfo().getGameType() != GameType.ADVENTURE) {
int i = Math.max(0, this.server.func_184108_a(worldserver));
int i = Math.max(0, this.server.getSpawnRadius(worldserver));
int j = MathHelper.floor(worldserver.getWorldBorder().getClosestDistance(blockposition.getX(), blockposition.getZ()));
if (j < i) {
i = j;
@ -233,7 +214,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
CraftWorld cworld = (CraftWorld) Bukkit.getServer().getWorld(this.spawnWorld);
if (cworld != null && this.getBedLocation() != null) {
world = cworld.getHandle();
position = PlayerEntity.func_213822_a(cworld.getHandle(), this.getBedLocation(), false).orElse(null);
position = PlayerEntity.checkBedValidRespawnPosition(cworld.getHandle(), this.getBedLocation(), false).orElse(null);
}
}
if (world == null || position == null) {
@ -244,7 +225,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
this.setPosition(position.getX(), position.getY(), position.getZ());
}
this.dimension = this.world.getDimension().getType();
this.interactionManager.func_73080_a((ServerWorld) world);
this.interactionManager.setWorld((ServerWorld) world);
}
@Inject(method = "tick", at = @At("HEAD"))
@ -330,31 +311,23 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
this.connection.sendPacket(new SCombatPacket(this.getCombatTracker(), SCombatPacket.Event.ENTITY_DIED));
}
this.spawnShoulderEntities();
this.bridge$dropExperience();
if (!event.getKeepInventory()) {
this.inventory.clear();
}
this.setSpectatingEntity((ServerPlayerEntity) (Object) this);
((CraftScoreboardManager) Bukkit.getScoreboardManager()).getScoreboardScores(ScoreCriteria.DEATH_COUNT, this.getScoreboardName(), Score::incrementScore);
LivingEntity entityliving = this.getAttackingEntity();
if (entityliving != null) {
this.addStat(Stats.ENTITY_KILLED_BY.get(entityliving.getType()));
entityliving.awardKillScore((ServerPlayerEntity) (Object) this, this.scoreValue, damagesource);
if (!this.world.isRemote && entityliving instanceof WitherEntity) {
boolean flag3 = false;
if (net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, (ServerPlayerEntity) (Object) this)) {
BlockPos blockposition = new BlockPos(this.posX, this.posY, this.posZ);
BlockState iblockdata = Blocks.WITHER_ROSE.getDefaultState();
if (this.world.getBlockState(blockposition).isAir() && iblockdata.isValidPosition(this.world, blockposition)) {
this.world.setBlockState(blockposition, iblockdata, 3);
flag3 = true;
}
}
if (!flag3) {
ItemEntity entityitem = new ItemEntity(this.world, this.posX, this.posY, this.posZ, new ItemStack(Items.WITHER_ROSE));
this.world.addEntity(entityitem);
}
}
this.bridge$createWitherRose(entityliving);
}
this.world.setEntityState((ServerPlayerEntity) (Object) this, (byte) 3);
this.addStat(Stats.DEATHS);
this.takeStat(Stats.CUSTOM.get(Stats.TIME_SINCE_DEATH));
this.takeStat(Stats.CUSTOM.get(Stats.TIME_SINCE_REST));
@ -378,177 +351,6 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
cir.setReturnValue(((WorldBridge) this.world).bridge$isPvpMode());
}
/**
* @author IzzelAliz
* @reason
*/
@Nullable
@Overwrite
// todo DimensionType getType
public Entity changeDimension(DimensionType dimensionmanager) {
PlayerTeleportEvent.TeleportCause cause = arclight$cause == null ? PlayerTeleportEvent.TeleportCause.UNKNOWN : arclight$cause;
arclight$cause = null;
if (!net.minecraftforge.common.ForgeHooks.onTravelToDimension((ServerPlayerEntity) (Object) this, dimensionmanager))
return null;
if (this.isSleeping()) {
return (ServerPlayerEntity) (Object) this;
}
DimensionType dimensionmanager2 = this.dimension;
if (dimensionmanager2 == DimensionType.THE_END && dimensionmanager == DimensionType.OVERWORLD) {
this.invulnerableDimensionChange = true;
this.detach();
this.func_71121_q().removePlayer((ServerPlayerEntity) (Object) this, true);
if (!this.queuedEndExit) {
this.queuedEndExit = true;
this.connection.sendPacket(new SChangeGameStatePacket(4, this.seenCredits ? 0.0f : 1.0f));
this.seenCredits = true;
}
return (ServerPlayerEntity) (Object) this;
}
ServerWorld worldserver = this.server.func_71218_a(dimensionmanager2);
ServerWorld worldserver2 = this.server.func_71218_a(dimensionmanager);
WorldInfo worlddata = this.world.getWorldInfo();
double d0 = this.posX;
double d2 = this.posY;
double d3 = this.posZ;
float f = this.rotationPitch;
float f2 = this.rotationYaw;
double d4 = 8.0;
float f3 = f2;
worldserver.getProfiler().startSection("moving");
if (worldserver2 != null) {
if (dimensionmanager2 == DimensionType.OVERWORLD && dimensionmanager == DimensionType.THE_NETHER) {
this.enteredNetherPosition = new Vec3d(this.posX, this.posY, this.posZ);
d0 /= 8.0;
d3 /= 8.0;
} else if (dimensionmanager2 == DimensionType.THE_NETHER && dimensionmanager == DimensionType.OVERWORLD) {
d0 *= 8.0;
d3 *= 8.0;
} else if (dimensionmanager2 == DimensionType.OVERWORLD && dimensionmanager == DimensionType.THE_END) {
BlockPos blockposition = worldserver2.getSpawnCoordinate();
d0 = blockposition.getX();
d2 = blockposition.getY();
d3 = blockposition.getZ();
f2 = 90.0f;
f = 0.0f;
}
}
Location enter = this.getBukkitEntity().getLocation();
Location exit = (worldserver2 == null) ? null : new Location(((WorldBridge) worldserver2).bridge$getWorld(), d0, d2, d3, f2, f);
PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null) {
return null;
}
exit = event.getTo();
if (exit == null) {
return null;
}
PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause);
Bukkit.getServer().getPluginManager().callEvent(tpEvent);
if (tpEvent.isCancelled() || tpEvent.getTo() == null) {
return null;
}
exit = tpEvent.getTo();
if (exit == null) {
return null;
}
worldserver2 = ((CraftWorld) exit.getWorld()).getHandle();
d0 = exit.getX();
d2 = exit.getY();
d3 = exit.getZ();
f2 = exit.getYaw();
f = exit.getPitch();
this.invulnerableDimensionChange = true;
dimensionmanager = worldserver2.getDimension().getType();
this.dimension = dimensionmanager;
net.minecraftforge.fml.network.NetworkHooks.sendDimensionDataPacket(this.connection.netManager, (ServerPlayerEntity) (Object) this);
this.connection.sendPacket(new SRespawnPacket(worldserver2.dimension.getType(), this.world.getWorldInfo().getGenerator(), this.interactionManager.getGameType()));
this.connection.sendPacket(new SServerDifficultyPacket(this.world.getDifficulty(), this.world.getWorldInfo().isDifficultyLocked()));
PlayerList playerlist = this.server.getPlayerList();
playerlist.updatePermissionLevel((ServerPlayerEntity) (Object) this);
worldserver.removePlayer((ServerPlayerEntity) (Object) this, true);
this.removed = false;
this.setLocationAndAngles(d0, d2, d3, f2, f);
worldserver.getProfiler().endSection();
worldserver.getProfiler().startSection("placing");
double d5 = Math.min(-2.9999872E7, worldserver2.getWorldBorder().minX() + 16.0);
double d6 = Math.min(-2.9999872E7, worldserver2.getWorldBorder().minZ() + 16.0);
double d7 = Math.min(2.9999872E7, worldserver2.getWorldBorder().maxX() - 16.0);
double d8 = Math.min(2.9999872E7, worldserver2.getWorldBorder().maxZ() - 16.0);
d0 = MathHelper.clamp(d0, d5, d7);
d3 = MathHelper.clamp(d3, d6, d8);
this.setLocationAndAngles(d0, d2, d3, f2, f);
if (dimensionmanager == DimensionType.THE_END) {
int i = MathHelper.floor(this.posX);
int j = MathHelper.floor(this.posY) - 1;
int k = MathHelper.floor(this.posZ);
boolean flag = true;
boolean flag2 = false;
BlockStateListPopulator blockList = new BlockStateListPopulator(worldserver2);
for (int l = -2; l <= 2; ++l) {
for (int i2 = -2; i2 <= 2; ++i2) {
for (int j2 = -1; j2 < 3; ++j2) {
int k2 = i + i2 * 1 + l * 0;
int l2 = j + j2;
int i3 = k + i2 * 0 - l * 1;
boolean flag3 = j2 < 0;
blockList.setBlockState(new BlockPos(k2, l2, i3), flag3 ? Blocks.OBSIDIAN.getDefaultState() : Blocks.AIR.getDefaultState(), 3);
}
}
}
org.bukkit.World bworld = ((WorldBridge) worldserver2).bridge$getWorld();
PortalCreateEvent portalEvent = new PortalCreateEvent((List) blockList.getList(), bworld, this.getBukkitEntity(), PortalCreateEvent.CreateReason.END_PLATFORM);
Bukkit.getPluginManager().callEvent(portalEvent);
if (!portalEvent.isCancelled()) {
blockList.updateList();
}
this.setLocationAndAngles(i, j, k, f2, 0.0f);
this.setMotion(Vec3d.ZERO);
} else if (!worldserver2.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f3)) {
worldserver2.getDefaultTeleporter().makePortal((ServerPlayerEntity) (Object) this);
worldserver2.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f3);
}
worldserver.getProfiler().endSection();
this.setWorld(worldserver2);
worldserver2.func_217447_b((ServerPlayerEntity) (Object) this);
this.func_213846_b(worldserver);
this.connection.setPlayerLocation(this.posX, this.posY, this.posZ, f2, f);
this.interactionManager.func_73080_a(worldserver2);
this.connection.sendPacket(new SPlayerAbilitiesPacket(this.abilities));
playerlist.func_72354_b((ServerPlayerEntity) (Object) this, worldserver2);
playerlist.sendInventory((ServerPlayerEntity) (Object) this);
for (EffectInstance mobeffect : this.getActivePotionEffects()) {
this.connection.sendPacket(new SPlayEntityEffectPacket(this.getEntityId(), mobeffect));
}
this.connection.sendPacket(new SPlaySoundEventPacket(1032, BlockPos.ZERO, 0, false));
this.lastExperience = -1;
this.lastHealth = -1.0f;
this.lastFoodLevel = -1;
PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), ((WorldBridge) worldserver).bridge$getWorld());
Bukkit.getPluginManager().callEvent(changeEvent);
net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerChangedDimensionEvent((ServerPlayerEntity) (Object) this, dimensionmanager2, dimensionmanager);
return (ServerPlayerEntity) (Object) this;
}
public Entity a(DimensionType dimensionmanager, final PlayerTeleportEvent.TeleportCause cause) {
bridge$pushChangeDimensionCause(cause);
return this.changeDimension(dimensionmanager);
}
@Override
public Either<PlayerEntity.SleepResult, Unit> sleep(BlockPos at, boolean force) {
return super.sleep(at, force).ifRight((p_213849_1_) -> {
this.addStat(Stats.SLEEP_IN_BED);
CriteriaTriggers.SLEPT_IN_BED.trigger((ServerPlayerEntity) (Object) this);
});
}
@Inject(method = "wakeUpPlayer", cancellable = true, at = @At("HEAD"))
private void arclight$notWake(boolean immediately, boolean updateWorldFlag, boolean setSpawn, CallbackInfo ci) {
if (!isSleeping()) ci.cancel();
}
public int nextContainerCounter() {
this.getNextWindowId();
return this.currentWindowId;
@ -677,21 +479,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
return listName;
}
@Inject(method = "setElytraFlying", cancellable = true, at = @At("HEAD"))
private void arclight$beginGlide(CallbackInfo ci) {
if (CraftEventFactory.callToggleGlideEvent((ServerPlayerEntity) (Object) this, true).isCancelled()) {
ci.cancel();
}
}
@Inject(method = "clearElytraFlying", cancellable = true, at = @At("HEAD"))
private void arclight$endGlide(CallbackInfo ci) {
if (CraftEventFactory.callToggleGlideEvent((ServerPlayerEntity) (Object) this, false).isCancelled()) {
ci.cancel();
}
}
@Inject(method = "func_200619_a", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/player/ServerPlayerEntity;stopRiding()V"))
@Inject(method = "teleport", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/player/ServerPlayerEntity;stopRiding()V"))
private void arclight$handleBy(ServerWorld world, double x, double y, double z, float yaw, float pitch, CallbackInfo ci) {
PlayerTeleportEvent.TeleportCause cause = arclight$cause == null ? PlayerTeleportEvent.TeleportCause.UNKNOWN : arclight$cause;
arclight$cause = null;
@ -701,7 +489,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
public void a(ServerWorld worldserver, double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) {
bridge$pushChangeDimensionCause(cause);
func_200619_a(worldserver, d0, d1, d2, f, f1);
teleport(worldserver, d0, d1, d2, f, f1);
}
public CraftPlayer getBukkitEntity() {
@ -721,8 +509,12 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
}
@Override
public Entity bridge$changeDimension(DimensionType dimensionType, PlayerTeleportEvent.TeleportCause cause) {
return a(dimensionType, cause);
public Optional<PlayerTeleportEvent.TeleportCause> bridge$getTeleportCause() {
try {
return Optional.ofNullable(arclight$cause);
} finally {
arclight$cause = null;
}
}
public long getPlayerTime() {

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.common.mixin.core.entity.projectile;
import io.izzel.arclight.common.bridge.entity.projectile.DamagingProjectileEntityBridge;
import io.izzel.arclight.common.mixin.core.entity.EntityMixin;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
@ -16,7 +17,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import io.izzel.arclight.common.bridge.entity.projectile.DamagingProjectileEntityBridge;
@Mixin(DamagingProjectileEntity.class)
public abstract class DamagingProjectileEntityMixin extends EntityMixin implements DamagingProjectileEntityBridge {
@ -26,6 +26,7 @@ public abstract class DamagingProjectileEntityMixin extends EntityMixin implemen
@Shadow public double accelerationY;
@Shadow public double accelerationZ;
@Shadow public LivingEntity shootingEntity;
@Shadow protected void onImpact(RayTraceResult result) {}
// @formatter:on
public float bukkitYield;

View File

@ -2,6 +2,9 @@ package io.izzel.arclight.common.mixin.core.entity.projectile;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.CampfireBlock;
import net.minecraft.entity.AreaEffectCloudEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
@ -11,7 +14,9 @@ import net.minecraft.item.ItemStack;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Potion;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import org.bukkit.craftbukkit.v.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityPotionEffectEvent;
@ -104,4 +109,18 @@ public abstract class PotionEntityMixin extends ThrowableEntityMixin {
entity.remove();
}
}
@Inject(method = "extinguishFires", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;extinguishFire(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Z"))
private void arclight$entityChangeBlock(BlockPos pos, Direction direction, CallbackInfo ci) {
if (CraftEventFactory.callEntityChangeBlockEvent((PotionEntity) (Object) this, pos.offset(direction), Blocks.AIR.getDefaultState()).isCancelled()) {
ci.cancel();
}
}
@Inject(method = "extinguishFires", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;playEvent(Lnet/minecraft/entity/player/PlayerEntity;ILnet/minecraft/util/math/BlockPos;I)V"))
private void arclight$entityChangeBlock2(BlockPos pos, Direction p_184542_2_, CallbackInfo ci, BlockState state) {
if (CraftEventFactory.callEntityChangeBlockEvent((PotionEntity) (Object) this, pos, state.with(CampfireBlock.LIT, false)).isCancelled()) {
ci.cancel();
}
}
}

View File

@ -0,0 +1,44 @@
package io.izzel.arclight.common.mixin.core.entity.projectile;
import io.izzel.arclight.common.bridge.entity.projectile.ProjectileItemEntityBridge;
import net.minecraft.entity.projectile.ProjectileItemEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.util.Util;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ProjectileItemEntity.class)
@Implements(@Interface(iface = ProjectileItemEntityBridge.Hack.class, prefix = "hack$"))
public abstract class ProjectileItemEntityMixin extends ThrowableEntityMixin {
// @formatter:off
@Shadow protected abstract Item shadow$getDefaultItem();
@Shadow @Final private static DataParameter<ItemStack> ITEMSTACK_DATA;
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public void setItem(ItemStack stack) {
if (stack.getItem() != this.shadow$getDefaultItem() || stack.hasTag()) {
this.getDataManager().set(ITEMSTACK_DATA, Util.make(stack.copy(), (itemStack) -> {
if (!itemStack.isEmpty()) {
itemStack.setCount(1);
}
}));
}
}
public Item hack$getDefaultItem() {
return this.shadow$getDefaultItem();
}
}

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.common.mixin.core.entity.projectile;
import io.izzel.arclight.api.ArclightVersion;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
@ -39,6 +40,9 @@ public abstract class SmallFireballEntityMixin extends DamagingProjectileEntityM
*/
@Overwrite
protected void onImpact(RayTraceResult result) {
if (ArclightVersion.atLeast(ArclightVersion.v1_15)) {
super.onImpact(result);
}
if (!this.world.isRemote) {
if (result.getType() == RayTraceResult.Type.ENTITY) {
Entity entity = ((EntityRayTraceResult) result).getEntity();

View File

@ -22,7 +22,7 @@ public abstract class WitherSkullEntityMixin extends DamagingProjectileEntityMix
@Inject(method = "onImpact", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;heal(F)V"))
private void arclight$heal(RayTraceResult result, CallbackInfo ci) {
((LivingEntityBridge) this.shootingEntity).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.REGEN);
((LivingEntityBridge) this.shootingEntity).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.WITHER);
}
@Inject(method = "onImpact", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;addPotionEffect(Lnet/minecraft/potion/EffectInstance;)Z"))

View File

@ -1,7 +1,6 @@
package io.izzel.arclight.common.mixin.core.fluid;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.fluid.FlowingFluid;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.IFluidState;
@ -9,7 +8,6 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
@ -20,7 +18,6 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.FluidLevelChangeEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -32,9 +29,6 @@ public abstract class FlowingFluidMixin {
// @formatter:off
@Shadow protected abstract boolean canFlow(IBlockReader worldIn, BlockPos fromPos, BlockState fromBlockState, Direction direction, BlockPos toPos, BlockState toBlockState, IFluidState toFluidState, Fluid fluidIn);
@Shadow protected abstract IFluidState calculateCorrectFlowingState(IWorldReader worldIn, BlockPos pos, BlockState blockStateIn);
@Shadow protected abstract int func_215667_a(World p_215667_1_, BlockPos p_215667_2_, IFluidState p_215667_3_, IFluidState p_215667_4_);
@Shadow protected abstract void flowAround(IWorld worldIn, BlockPos pos, IFluidState stateIn);
// @formatter:on
@Inject(method = "flowAround", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/fluid/FlowingFluid;flowInto(Lnet/minecraft/world/IWorld;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/Direction;Lnet/minecraft/fluid/IFluidState;)V"))
@ -59,35 +53,13 @@ public abstract class FlowingFluidMixin {
}
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public void tick(World worldIn, BlockPos pos, IFluidState state) {
if (!state.isSource()) {
IFluidState ifluidstate = this.calculateCorrectFlowingState(worldIn, pos, worldIn.getBlockState(pos));
int i = this.func_215667_a(worldIn, pos, state, ifluidstate);
if (ifluidstate.isEmpty()) {
state = ifluidstate;
FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(worldIn, pos, Blocks.AIR.getDefaultState());
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z"))
private boolean arclight$fluidLevelChange(World world, BlockPos pos, BlockState newState, int flags) {
FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(world, pos, newState);
if (event.isCancelled()) {
return;
return false;
} else {
return world.setBlockState(pos, ((CraftBlockData) event.getNewData()).getState(), flags);
}
worldIn.setBlockState(pos, ((CraftBlockData) event.getNewData()).getState(), 3);
} else if (!ifluidstate.equals(state)) {
state = ifluidstate;
BlockState blockstate = ifluidstate.getBlockState();
FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(worldIn, pos, blockstate);
if (event.isCancelled()) {
return;
}
worldIn.setBlockState(pos, ((CraftBlockData) event.getNewData()).getState(), 2);
worldIn.getPendingFluidTicks().scheduleTick(pos, ifluidstate.getFluid(), i);
worldIn.notifyNeighborsOfStateChange(pos, blockstate.getBlock());
}
}
this.flowAround(worldIn, pos, state);
}
}

View File

@ -4,8 +4,10 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.fluid.IFluidState;
import net.minecraft.fluid.LavaFluid;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameRules;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraftforge.event.ForgeEventFactory;
@ -13,6 +15,10 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Random;
@ -77,4 +83,16 @@ public abstract class LavaFluidMixin {
}
}
@Inject(method = "flowInto", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/IWorld;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z"))
private void arclight$returnIfFail(IWorld worldIn, BlockPos pos, BlockState blockStateIn, Direction direction, IFluidState fluidStateIn, CallbackInfo ci) {
if (!arclight$success) ci.cancel();
}
private transient boolean arclight$success;
@Redirect(method = "flowInto", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/IWorld;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z"))
private boolean arclight$blockFromTo(IWorld iWorld, BlockPos pos, BlockState newState, int flags) {
return arclight$success = CraftEventFactory.handleBlockFormEvent(iWorld.getWorld(), pos, newState, flags);
}
}

View File

@ -8,6 +8,8 @@ import net.minecraft.inventory.IInventory;
import net.minecraft.tileentity.EnderChestTileEntity;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryHolder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@ -39,6 +41,13 @@ public abstract class EnderChestInventoryMixin extends InventoryMixin implements
return ((PlayerEntityBridge) owner).bridge$getBukkitEntity();
}
@Override
public void setOwner(InventoryHolder owner) {
if (owner instanceof HumanEntity) {
this.owner = ((CraftHumanEntity) owner).getHandle();
}
}
@Override
public Location getLocation() {
return CraftBlock.at(this.associatedChest.getWorld(), this.associatedChest.getPos()).getLocation();

View File

@ -5,9 +5,7 @@ import com.google.common.collect.Sets;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.world.ExplosionBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.enchantment.ProtectionEnchantment;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
@ -16,27 +14,17 @@ import net.minecraft.entity.item.TNTEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.DamagingProjectileEntity;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.ItemStack;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.loot.LootContext;
import net.minecraft.world.storage.loot.LootParameters;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@ -51,7 +39,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
@Mixin(Explosion.class)
@ -65,8 +52,6 @@ public abstract class ExplosionMixin implements ExplosionBridge {
@Shadow @Final private double x;
@Shadow @Final private double y;
@Shadow @Final private double z;
@Shadow @Final private boolean causesFire;
@Shadow @Final private Random random;
@Shadow @Final public Entity exploder;
@Shadow public abstract DamageSource getDamageSource();
@Shadow @Final private Map<PlayerEntity, Vec3d> playerKnockbackMap;
@ -76,8 +61,6 @@ public abstract class ExplosionMixin implements ExplosionBridge {
@Accessor("mode") public abstract Explosion.Mode bridge$getMode();
// @formatter:on
public boolean wasCanceled = false;
@Inject(method = "<init>(Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;DDDFZLnet/minecraft/world/Explosion$Mode;)V",
at = @At("RETURN"))
public void arclight$adjustSize(World worldIn, Entity exploderIn, double xIn, double yIn, double zIn, float sizeIn, boolean causesFireIn, Explosion.Mode modeIn, CallbackInfo ci) {
@ -147,13 +130,12 @@ public abstract class ExplosionMixin implements ExplosionBridge {
net.minecraftforge.event.ForgeEventFactory.onExplosionDetonate(this.world, (Explosion) (Object) this, list, f3);
Vec3d vec3d = new Vec3d(this.x, this.y, this.z);
for (int k2 = 0; k2 < list.size(); ++k2) {
Entity entity = list.get(k2);
for (Entity entity : list) {
if (!entity.isImmuneToExplosions()) {
double d12 = MathHelper.sqrt(entity.getDistanceSq(new Vec3d(this.x, this.y, this.z))) / f3;
double d12 = MathHelper.sqrt(entity.getDistanceSq(vec3d)) / f3;
if (d12 <= 1.0D) {
double d5 = entity.posX - this.x;
double d7 = entity.posY + (double) entity.getEyeHeight() - this.y;
double d7 = ((EntityBridge) entity).bridge$getEyeHeight() - this.y;
double d9 = entity.posZ - this.z;
double d13 = MathHelper.sqrt(d5 * d5 + d7 * d7 + d9 * d9);
if (d13 != 0.0D) {
@ -190,81 +172,8 @@ public abstract class ExplosionMixin implements ExplosionBridge {
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public void doExplosionB(boolean spawnParticles) {
this.world.playSound(null, this.x, this.y, this.z, SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 4.0F, (1.0F + (this.world.rand.nextFloat() - this.world.rand.nextFloat()) * 0.2F) * 0.7F);
boolean flag = this.mode != Explosion.Mode.NONE;
if (!(this.size < 2.0F) && flag) {
this.world.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
} else {
this.world.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
}
if (flag) {
float yield = arclight$callBlockExplodeEvent();
if (Float.isNaN(yield)) {
this.wasCanceled = true;
return;
}
for (BlockPos blockpos : this.affectedBlockPositions) {
BlockState blockstate = this.world.getBlockState(blockpos);
Block block = blockstate.getBlock();
if (spawnParticles) {
double d0 = ((float) blockpos.getX() + this.world.rand.nextFloat());
double d1 = ((float) blockpos.getY() + this.world.rand.nextFloat());
double d2 = ((float) blockpos.getZ() + this.world.rand.nextFloat());
double d3 = d0 - this.x;
double d4 = d1 - this.y;
double d5 = d2 - this.z;
double d6 = MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
d3 = d3 / d6;
d4 = d4 / d6;
d5 = d5 / d6;
double d7 = 0.5D / (d6 / (double) this.size + 0.1D);
d7 = d7 * (double) (this.world.rand.nextFloat() * this.world.rand.nextFloat() + 0.3F);
d3 = d3 * d7;
d4 = d4 * d7;
d5 = d5 * d7;
this.world.addParticle(ParticleTypes.POOF, (d0 + this.x) / 2.0D, (d1 + this.y) / 2.0D, (d2 + this.z) / 2.0D, d3, d4, d5);
this.world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, d3, d4, d5);
}
if (!blockstate.isAir(this.world, blockpos)) {
if (this.world instanceof ServerWorld && blockstate.canDropFromExplosion(this.world, blockpos, (Explosion) (Object) this)) {
TileEntity tileentity = blockstate.hasTileEntity() ? this.world.getTileEntity(blockpos) : null;
LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerWorld) this.world)).withRandom(this.world.rand).withParameter(LootParameters.POSITION, blockpos).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, tileentity);
if (this.mode == Explosion.Mode.DESTROY || yield < 1.0F) {
lootcontext$builder.withParameter(LootParameters.EXPLOSION_RADIUS, 1.0F / yield);
}
Block.spawnDrops(blockstate, lootcontext$builder);
}
blockstate.onBlockExploded(this.world, blockpos, (Explosion) (Object) this);
}
}
}
if (this.causesFire) {
for (BlockPos blockPos : this.affectedBlockPositions) {
if (this.world.getBlockState(blockPos).isAir(world, blockPos) && this.world.getBlockState(blockPos.down()).isOpaqueCube(this.world, blockPos.down()) && this.random.nextInt(3) == 0) {
BlockIgniteEvent event = CraftEventFactory.callBlockIgniteEvent(this.world, blockPos.getX(), blockPos.getY(), blockPos.getZ(), (Explosion) (Object) this);
if (!event.isCancelled()) {
this.world.setBlockState(blockPos, Blocks.FIRE.getDefaultState());
}
}
}
}
}
private float arclight$callBlockExplodeEvent() {
@Override
public float bridge$callBlockExplodeEvent() {
org.bukkit.World world = ((WorldBridge) this.world).bridge$getWorld();
org.bukkit.entity.Entity exploder = this.exploder == null ? null : ((EntityBridge) this.exploder).bridge$getBukkitEntity();
Location location = new Location(world, this.x, this.y, this.z);
@ -272,7 +181,7 @@ public abstract class ExplosionMixin implements ExplosionBridge {
for (int i = this.affectedBlockPositions.size() - 1; i >= 0; i--) {
BlockPos blockPos = this.affectedBlockPositions.get(i);
org.bukkit.block.Block block = world.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ());
if (block.getType() != Material.AIR && block.getType() != Material.CAVE_AIR && block.getType() != Material.VOID_AIR) {
if (!block.getType().isAir()) {
blockList.add(block);
}
}
@ -323,9 +232,4 @@ public abstract class ExplosionMixin implements ExplosionBridge {
return null;
}
}
@Override
public boolean bridge$wasCancelled() {
return wasCanceled;
}
}

View File

@ -26,14 +26,14 @@ public interface IBlockReaderMixin extends IBlockReaderBridge {
default BlockRayTraceResult rayTraceBlock(RayTraceContext context, BlockPos pos) {
BlockState blockstate = this.getBlockState(pos);
IFluidState ifluidstate = this.getFluidState(pos);
Vec3d vec3d = context.func_222253_b();
Vec3d vec3d1 = context.func_222250_a();
Vec3d vec3d = context.getStartVec();
Vec3d vec3d1 = context.getStartVec();
VoxelShape voxelshape = context.getBlockShape(blockstate, (IBlockReader) this, pos);
BlockRayTraceResult blockraytraceresult = this.rayTraceBlocks(vec3d, vec3d1, pos, voxelshape, blockstate);
VoxelShape voxelshape1 = context.getFluidShape(ifluidstate, (IBlockReader) this, pos);
BlockRayTraceResult blockraytraceresult1 = voxelshape1.rayTrace(vec3d, vec3d1, pos);
double d0 = blockraytraceresult == null ? Double.MAX_VALUE : context.func_222253_b().squareDistanceTo(blockraytraceresult.getHitVec());
double d1 = blockraytraceresult1 == null ? Double.MAX_VALUE : context.func_222253_b().squareDistanceTo(blockraytraceresult1.getHitVec());
double d0 = blockraytraceresult == null ? Double.MAX_VALUE : context.getStartVec().squareDistanceTo(blockraytraceresult.getHitVec());
double d1 = blockraytraceresult1 == null ? Double.MAX_VALUE : context.getStartVec().squareDistanceTo(blockraytraceresult1.getHitVec());
return d0 <= d1 ? blockraytraceresult : blockraytraceresult1;
}

View File

@ -1,9 +1,11 @@
package io.izzel.arclight.common.mixin.core.world;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.bridge.world.TeleporterBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.mod.util.ArclightBlockPopulator;
import net.minecraft.block.BlockState;
import net.minecraft.block.pattern.BlockPattern;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.Teleporter;
@ -21,7 +23,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Mixin(Teleporter.class)
public class TeleporterMixin {
public class TeleporterMixin implements TeleporterBridge {
// @formatter:off
@Shadow @Final protected ServerWorld world;
@ -56,4 +58,16 @@ public class TeleporterMixin {
}
arclight$populator = null;
}
@Override
public boolean bridge$makePortal(Entity entityIn, BlockPos pos, int createRadius) {
// todo
return false;
}
@Override
public BlockPattern.PortalInfo bridge$placeInPortal(Entity p_222268_1_, BlockPos pos, float p_222268_2_, int searchRadius, boolean searchOnly) {
// todo
return null;
}
}

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.world;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.ai.attributes.AttributeMap;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.item.ItemFrameEntity;
@ -20,6 +21,7 @@ import net.minecraft.network.play.server.SEntityPacket;
import net.minecraft.network.play.server.SEntityPropertiesPacket;
import net.minecraft.network.play.server.SEntityTeleportPacket;
import net.minecraft.network.play.server.SEntityVelocityPacket;
import net.minecraft.network.play.server.SMountEntityPacket;
import net.minecraft.network.play.server.SPlayEntityEffectPacket;
import net.minecraft.network.play.server.SSetPassengersPacket;
import net.minecraft.network.play.server.SSpawnMobPacket;
@ -29,7 +31,6 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.TrackedEntity;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.MapData;
import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerVelocityEvent;
@ -76,7 +77,6 @@ public abstract class TrackedEntityMixin {
@Shadow protected abstract void sendPacket(IPacket<?> p_219451_1_);
// @formatter:on
@Shadow @Final private static Logger LOGGER;
private Set<ServerPlayerEntity> trackedPlayers;
@Inject(method = "<init>", at = @At("RETURN"))
@ -136,7 +136,7 @@ public abstract class TrackedEntityMixin {
++this.ticksSinceAbsoluteTeleport;
int i = MathHelper.floor(this.trackedEntity.rotationYaw * 256.0f / 360.0f);
int j = MathHelper.floor(this.trackedEntity.rotationPitch * 256.0f / 360.0f);
Vec3d vec3d = new Vec3d(this.trackedEntity.posX, this.trackedEntity.posY, this.trackedEntity.posZ).subtract(SEntityPacket.func_218744_a(this.encodedPosX, this.encodedPosY, this.encodedPosZ));
Vec3d vec3d = this.trackedEntity.getPositionVec().subtract(SEntityPacket.func_218744_a(this.encodedPosX, this.encodedPosY, this.encodedPosZ));
boolean flag2 = vec3d.lengthSquared() >= 7.62939453125E-6;
IPacket<?> packet2 = null;
boolean flag3 = flag2 || this.updateCounter % 60 == 0;
@ -266,6 +266,12 @@ public abstract class TrackedEntityMixin {
if (this.trackedEntity.isPassenger()) {
consumer.accept(new SSetPassengersPacket(this.trackedEntity.getRidingEntity()));
}
if (this.trackedEntity instanceof MobEntity) {
MobEntity mobentity = (MobEntity) this.trackedEntity;
if (mobentity.getLeashed()) {
consumer.accept(new SMountEntityPacket(mobentity, mobentity.getLeashHolder()));
}
}
}
@Inject(method = "sendMetadata", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/TrackedEntity;sendPacket(Lnet/minecraft/network/IPacket;)V"))

View File

@ -0,0 +1,17 @@
package io.izzel.arclight.common.mixin.core.world.chunk.storage;
import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge;
import net.minecraft.world.chunk.storage.ChunkLoader;
import net.minecraft.world.dimension.DimensionType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@Mixin(ChunkLoader.class)
public class ChunkLoaderMixin {
@ModifyArg(method = "updateChunkData", index = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/gen/feature/structure/LegacyStructureDataUtil;func_215130_a(Lnet/minecraft/world/dimension/DimensionType;Lnet/minecraft/world/storage/DimensionSavedDataManager;)Lnet/minecraft/world/gen/feature/structure/LegacyStructureDataUtil;"))
private DimensionType arclight$dimType(DimensionType dim) {
return ((DimensionTypeBridge) dim).bridge$getType();
}
}

View File

@ -0,0 +1,24 @@
package io.izzel.arclight.common.mixin.v1_15.block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.LilyPadBlock;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LilyPadBlock.class)
public class LilyPadBlockMixin_1_15 {
@Inject(method = "onEntityCollision", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;destroyBlock(Lnet/minecraft/util/math/BlockPos;ZLnet/minecraft/entity/Entity;)Z"))
public void arclight$entityChangeBlock(BlockState state, World worldIn, BlockPos pos, Entity entityIn, CallbackInfo ci) {
if (CraftEventFactory.callEntityChangeBlockEvent(entityIn, pos, Blocks.AIR.getDefaultState()).isCancelled()) {
ci.cancel();
}
}
}

View File

@ -7,6 +7,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@ -21,14 +22,16 @@ import net.minecraftforge.common.util.ITeleporter;
import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityPortalEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable;
import java.util.Random;
@Mixin(Entity.class)
public abstract class EntityMixin_1_15 {
public abstract class EntityMixin_1_15 implements EntityBridge {
// @formatter:off
@Shadow public World world;
@ -47,6 +50,12 @@ public abstract class EntityMixin_1_15 {
@Shadow public abstract double getPosY();
@Shadow public abstract Direction getTeleportDirection();
@Shadow public abstract EntityType<?> getType();
@Shadow @Final protected EntityDataManager dataManager;
@Shadow public abstract boolean isInvisible();
@Shadow @Final protected Random rand;
@Shadow public abstract float getWidth();
@Shadow public abstract float getHeight();
@Shadow public abstract double getPosYEye();
// @formatter:on
/**
@ -156,4 +165,9 @@ public abstract class EntityMixin_1_15 {
return null;
}
}
@Override
public double bridge$getEyeHeight() {
return this.getPosYEye();
}
}

View File

@ -0,0 +1,274 @@
package io.izzel.arclight.common.mixin.v1_15.entity;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.item.ExperienceOrbEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectInstance;
import net.minecraft.util.DamageSource;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.living.PotionEvent;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import javax.annotation.Nullable;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Mixin(LivingEntity.class)
public abstract class LivingEntityMixin_1_15 extends EntityMixin_1_15 implements LivingEntityBridge {
// @formatter:off
@Shadow @Final private static DataParameter<Integer> POTION_EFFECTS;
@Shadow @Final private static DataParameter<Boolean> HIDE_PARTICLES;
@Shadow @Final public Map<Effect, EffectInstance> activePotionsMap;
@Shadow public boolean potionsNeedUpdate;
@Shadow protected abstract void onFinishedPotionEffect(EffectInstance effect);
@Shadow protected abstract void onChangedPotionEffect(EffectInstance id, boolean reapply);
@Shadow protected abstract void updatePotionMetadata();
@Shadow public abstract boolean removePotionEffect(Effect effectIn);
@Shadow public abstract boolean isPotionApplicable(EffectInstance potioneffectIn);
@Shadow protected abstract void onNewPotionEffect(EffectInstance id);
@Shadow @Nullable public abstract EffectInstance removeActivePotionEffect(@Nullable Effect potioneffectin);
@Shadow public int deathTime;
@Shadow protected abstract void createWitherRose(@Nullable LivingEntity p_226298_1_);
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void onDeathUpdate() {
++this.deathTime;
if (this.deathTime >= 20 && !this.removed) {
this.remove((Object) this instanceof ServerPlayerEntity); //Forge keep data until we revive player
for (int k = 0; k < 20; ++k) {
double d2 = this.rand.nextGaussian() * 0.02D;
double d0 = this.rand.nextGaussian() * 0.02D;
double d1 = this.rand.nextGaussian() * 0.02D;
this.world.addParticle(ParticleTypes.POOF, this.getPosX() + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), this.getPosY() + (double) (this.rand.nextFloat() * this.getHeight()), this.getPosZ() + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), d2, d0, d1);
}
}
}
@Redirect(method = "spawnDrops", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;dropExperience()V"))
private void arclight$dropLater(LivingEntity livingEntity) {
}
@Inject(method = "spawnDrops", at = @At("RETURN"))
private void arclight$dropLast(DamageSource damageSourceIn, CallbackInfo ci) {
this.dropExperience();
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void dropExperience() {
// if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT))) {
if (true) {
int i = bridge$getExpToDrop();
while (i > 0) {
int j = ExperienceOrbEntity.getXPSplit(i);
i -= j;
this.world.addEntity(new ExperienceOrbEntity(this.world, this.getPosX(), this.getPosY(), this.getPosZ(), j));
}
bridge$setExpToDrop(0);
}
}
private boolean isTickingEffects = false;
private List<Map.Entry<Either<EffectInstance, Effect>, EntityPotionEffectEvent.Cause>> effectsToProcess = Lists.newArrayList();
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void updatePotionEffects() {
this.isTickingEffects = true;
Iterator<Effect> iterator = this.activePotionsMap.keySet().iterator();
try {
while (iterator.hasNext()) {
Effect effect = iterator.next();
EffectInstance effectinstance = this.activePotionsMap.get(effect);
if (!effectinstance.tick((LivingEntity) (Object) this, () -> {
onChangedPotionEffect(effectinstance, true);
})) {
if (!this.world.isRemote && !MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionExpiryEvent((LivingEntity) (Object) this, effectinstance))) {
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, null, EntityPotionEffectEvent.Cause.EXPIRATION);
if (event.isCancelled()) {
continue;
}
iterator.remove();
this.onFinishedPotionEffect(effectinstance);
}
} else if (effectinstance.getDuration() % 600 == 0) {
this.onChangedPotionEffect(effectinstance, false);
}
}
} catch (ConcurrentModificationException ignored) {
}
isTickingEffects = false;
for (Map.Entry<Either<EffectInstance, Effect>, EntityPotionEffectEvent.Cause> e : effectsToProcess) {
Either<EffectInstance, Effect> either = e.getKey();
EntityPotionEffectEvent.Cause cause = e.getValue();
bridge$pushEffectCause(cause);
if (either.left().isPresent()) {
addPotionEffect(either.left().get());
} else {
removePotionEffect(either.right().get());
}
}
effectsToProcess.clear();
if (this.potionsNeedUpdate) {
if (!this.world.isRemote) {
this.updatePotionMetadata();
}
this.potionsNeedUpdate = false;
}
int i = this.dataManager.get(POTION_EFFECTS);
boolean flag1 = this.dataManager.get(HIDE_PARTICLES);
if (i > 0) {
boolean flag;
if (this.isInvisible()) {
flag = this.rand.nextInt(15) == 0;
} else {
flag = this.rand.nextBoolean();
}
if (flag1) {
flag &= this.rand.nextInt(5) == 0;
}
if (flag && i > 0) {
double d0 = (double) (i >> 16 & 255) / 255.0D;
double d1 = (double) (i >> 8 & 255) / 255.0D;
double d2 = (double) (i >> 0 & 255) / 255.0D;
this.world.addParticle(flag1 ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, this.getPosX() + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), this.getPosY() + this.rand.nextDouble() * (double) this.getHeight(), this.getPosZ() + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), d0, d1, d2);
}
}
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public boolean addPotionEffect(EffectInstance effectInstanceIn) {
EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN);
if (isTickingEffects) {
effectsToProcess.add(Maps.immutableEntry(Either.left(effectInstanceIn), cause));
return true;
}
if (!this.isPotionApplicable(effectInstanceIn)) {
return false;
} else {
EffectInstance effectinstance = this.activePotionsMap.get(effectInstanceIn.getPotion());
boolean override = false;
if (effectinstance != null) {
override = new EffectInstance(effectinstance).combine(effectInstanceIn);
}
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn, cause, override);
if (event.isCancelled()) {
return false;
}
MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionAddedEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn));
if (effectinstance == null) {
this.activePotionsMap.put(effectInstanceIn.getPotion(), effectInstanceIn);
this.onNewPotionEffect(effectInstanceIn);
return true;
} else if (event.isOverride()) {
effectinstance.combine(effectInstanceIn);
this.onChangedPotionEffect(effectinstance, true);
return true;
} else {
return false;
}
}
}
@SuppressWarnings("unused") // mock
public EffectInstance c(@Nullable Effect potioneffectin, EntityPotionEffectEvent.Cause cause) {
bridge$pushEffectCause(cause);
return removeActivePotionEffect(potioneffectin);
}
@Inject(method = "removeActivePotionEffect", at = @At("HEAD"))
public void arclight$clearActive(Effect effect, CallbackInfoReturnable<EffectInstance> cir) {
EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN);
if (isTickingEffects) {
effectsToProcess.add(Maps.immutableEntry(Either.right(effect), cause));
cir.setReturnValue(null);
return;
}
EffectInstance effectInstance = this.activePotionsMap.get(effect);
if (effectInstance == null) {
cir.setReturnValue(null);
return;
}
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectInstance, null, cause);
if (event.isCancelled()) {
cir.setReturnValue(null);
}
}
private transient boolean arclight$fallSuccess;
@Inject(method = "onLivingFall", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z"))
public void arclight$fall(float distance, float damageMultiplier, CallbackInfoReturnable<Boolean> cir) {
if (!arclight$fallSuccess) {
cir.setReturnValue(true);
}
}
@Redirect(method = "onLivingFall", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z"))
public boolean arclight$fall(LivingEntity livingEntity, DamageSource source, float amount) {
return arclight$fallSuccess = livingEntity.attackEntityFrom(source, amount);
}
@Override
public void bridge$dropExperience() {
this.dropExperience();
}
@Override
public void bridge$createWitherRose(LivingEntity entity) {
this.createWitherRose(entity);
}
}

View File

@ -0,0 +1,177 @@
package io.izzel.arclight.common.mixin.v1_15.entity.boss;
import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityPredicate;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.boss.WitherEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.Difficulty;
import net.minecraft.world.Explosion;
import net.minecraft.world.server.ServerBossInfo;
import net.minecraftforge.event.ForgeEventFactory;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import java.util.List;
@Mixin(WitherEntity.class)
public abstract class WitherEntityMixin_1_15 extends CreatureEntityMixin {
// @formatter:off
@Shadow public abstract int getInvulTime();
@Shadow public abstract void setInvulTime(int time);
@Shadow @Final private int[] nextHeadUpdate;
@Shadow @Final private int[] idleHeadUpdates;
@Shadow protected abstract void launchWitherSkullToCoords(int p_82209_1_, double x, double y, double z, boolean invulnerable);
@Shadow public abstract int getWatchedTargetId(int head);
@Shadow public abstract void updateWatchedTargetId(int targetOffset, int newId);
@Shadow protected abstract void launchWitherSkullToEntity(int p_82216_1_, LivingEntity p_82216_2_);
@Shadow @Final private static EntityPredicate field_213798_bB;
@Shadow private int blockBreakCounter;
@Shadow @Final public ServerBossInfo bossInfo;
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void updateAITasks() {
if (this.getInvulTime() > 0) {
int j1 = this.getInvulTime() - 1;
if (j1 <= 0) {
Explosion.Mode explosion$mode = ForgeEventFactory.getMobGriefingEvent(this.world, (WitherEntity) (Object) this) ? Explosion.Mode.DESTROY : Explosion.Mode.NONE;
ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
this.world.createExplosion((WitherEntity) (Object) this, this.posX, this.bridge$getEyeHeight(), this.posZ, event.getRadius(), event.getFire(), explosion$mode);
}
this.world.playBroadcastSound(1023, new BlockPos((WitherEntity) (Object) this), 0);
}
this.setInvulTime(j1);
if (this.ticksExisted % 10 == 0) {
bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.WITHER_SPAWN);
this.heal(10.0F);
}
} else {
super.updateAITasks();
for (int i = 1; i < 3; ++i) {
if (this.ticksExisted >= this.nextHeadUpdate[i - 1]) {
this.nextHeadUpdate[i - 1] = this.ticksExisted + 10 + this.rand.nextInt(10);
if (this.world.getDifficulty() == Difficulty.NORMAL || this.world.getDifficulty() == Difficulty.HARD) {
int j3 = i - 1;
int k3 = this.idleHeadUpdates[i - 1];
this.idleHeadUpdates[j3] = this.idleHeadUpdates[i - 1] + 1;
if (k3 > 15) {
float f = 10.0F;
float f1 = 5.0F;
double d0 = MathHelper.nextDouble(this.rand, this.posX - 10.0D, this.posX + 10.0D);
double d1 = MathHelper.nextDouble(this.rand, this.posY - 5.0D, this.posY + 5.0D);
double d2 = MathHelper.nextDouble(this.rand, this.posZ - 10.0D, this.posZ + 10.0D);
this.launchWitherSkullToCoords(i + 1, d0, d1, d2, true);
this.idleHeadUpdates[i - 1] = 0;
}
}
int k1 = this.getWatchedTargetId(i);
if (k1 > 0) {
Entity entity = this.world.getEntityByID(k1);
if (entity != null && entity.isAlive() && !(this.getDistanceSq(entity) > 900.0D) && this.canEntityBeSeen(entity)) {
if (entity instanceof PlayerEntity && ((PlayerEntity) entity).abilities.disableDamage) {
this.updateWatchedTargetId(i, 0);
} else {
this.launchWitherSkullToEntity(i + 1, (LivingEntity) entity);
this.nextHeadUpdate[i - 1] = this.ticksExisted + 40 + this.rand.nextInt(20);
this.idleHeadUpdates[i - 1] = 0;
}
} else {
this.updateWatchedTargetId(i, 0);
}
} else {
List<LivingEntity> list = this.world.getTargettableEntitiesWithinAABB(LivingEntity.class, field_213798_bB, (WitherEntity) (Object) this, this.getBoundingBox().grow(20.0D, 8.0D, 20.0D));
for (int j2 = 0; j2 < 10 && !list.isEmpty(); ++j2) {
LivingEntity livingentity = list.get(this.rand.nextInt(list.size()));
if (livingentity != (Object) this && livingentity.isAlive() && this.canEntityBeSeen(livingentity)) {
if (livingentity instanceof PlayerEntity) {
if (!((PlayerEntity) livingentity).abilities.disableDamage) {
if (CraftEventFactory.callEntityTargetLivingEvent((WitherEntity) (Object) this, livingentity, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled())
continue;
this.updateWatchedTargetId(i, livingentity.getEntityId());
}
} else {
if (CraftEventFactory.callEntityTargetLivingEvent((WitherEntity) (Object) this, livingentity, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled())
continue;
this.updateWatchedTargetId(i, livingentity.getEntityId());
}
break;
}
list.remove(livingentity);
}
}
}
}
if (this.getAttackTarget() != null) {
this.updateWatchedTargetId(0, this.getAttackTarget().getEntityId());
} else {
this.updateWatchedTargetId(0, 0);
}
if (this.blockBreakCounter > 0) {
--this.blockBreakCounter;
if (this.blockBreakCounter == 0 && ForgeEventFactory.getMobGriefingEvent(this.world, (WitherEntity) (Object) this)) {
int i1 = MathHelper.floor(this.posY);
int l1 = MathHelper.floor(this.posX);
int i2 = MathHelper.floor(this.posZ);
boolean flag = false;
for (int k2 = -1; k2 <= 1; ++k2) {
for (int l2 = -1; l2 <= 1; ++l2) {
for (int j = 0; j <= 3; ++j) {
int i3 = l1 + k2;
int k = i1 + j;
int l = i2 + l2;
BlockPos blockpos = new BlockPos(i3, k, l);
BlockState blockstate = this.world.getBlockState(blockpos);
if (blockstate.canEntityDestroy(this.world, blockpos, (WitherEntity) (Object) this) && ForgeEventFactory.onEntityDestroyBlock((WitherEntity) (Object) this, blockpos, blockstate)) {
if (CraftEventFactory.callEntityChangeBlockEvent((WitherEntity) (Object) this, blockpos, Blocks.AIR.getDefaultState()).isCancelled()) {
continue;
}
flag = this.world.destroyBlock(blockpos, true, (WitherEntity) (Object) this) || flag;
}
}
}
}
if (flag) {
this.world.playEvent(null, 1022, new BlockPos((WitherEntity) (Object) this), 0);
}
}
}
if (this.ticksExisted % 20 == 0) {
bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.REGEN);
this.heal(1.0F);
}
this.bossInfo.setPercent(this.getHealth() / this.getMaxHealth());
}
}
}

View File

@ -0,0 +1,18 @@
package io.izzel.arclight.common.mixin.v1_15.entity.item;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ItemEntity.class)
public class ItemEntityMixin_1_15 {
@Redirect(method = "func_226531_a_", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/item/ItemEntity;setItem(Lnet/minecraft/item/ItemStack;)V"))
private static void arclight$setNonEmpty(ItemEntity itemEntity, ItemStack stack) {
if (!stack.isEmpty()) {
itemEntity.setItem(stack);
}
}
}

View File

@ -0,0 +1,24 @@
package io.izzel.arclight.common.mixin.v1_15.entity.monster;
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
import net.minecraft.entity.Entity;
import net.minecraft.entity.monster.AbstractRaiderEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.world.raid.Raid;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(AbstractRaiderEntity.class)
public class AbstractRaiderEntityMixin {
@Inject(method = "onDeath", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;addPotionEffect(Lnet/minecraft/potion/EffectInstance;)Z"))
private void arclight$raid(DamageSource cause, CallbackInfo ci, Entity entity, Raid raid, ItemStack itemStack, PlayerEntity playerEntity) {
((PlayerEntityBridge) playerEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.PATROL_CAPTAIN);
}
}

View File

@ -0,0 +1,22 @@
package io.izzel.arclight.common.mixin.v1_15.entity.monster;
import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.monster.RavagerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(RavagerEntity.class)
public abstract class RavagerEntityMixin_1_15 extends CreatureEntityMixin {
@Redirect(method = "livingTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;destroyBlock(Lnet/minecraft/util/math/BlockPos;ZLnet/minecraft/entity/Entity;)Z"))
private boolean arclight$entityChangeBlock(World world, BlockPos pos, boolean p_225521_2_, Entity entityIn) {
return !CraftEventFactory.callEntityChangeBlockEvent((RavagerEntity) (Object) this, pos, Blocks.AIR.getDefaultState()).isCancelled()
&& world.destroyBlock(pos, p_225521_2_, entityIn);
}
}

View File

@ -0,0 +1,19 @@
package io.izzel.arclight.common.mixin.v1_15.entity.monster;
import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin;
import net.minecraft.entity.monster.ShulkerEntity;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.world.server.ServerWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ShulkerEntity.class)
public abstract class ShulkerEntityMixin_1_15 extends CreatureEntityMixin {
@Inject(method = "notifyDataManagerChange", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/monster/ShulkerEntity;forceSetPosition(DDD)V"))
private void arclight$chunkCheck(DataParameter<?> key, CallbackInfo ci) {
if (valid) ((ServerWorld) this.world).chunkCheck((ShulkerEntity) (Object) this);
}
}

View File

@ -0,0 +1,57 @@
package io.izzel.arclight.common.mixin.v1_15.entity.monster;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.mixin.core.entity.monster.ZombieEntityMixin;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.monster.ZombiePigmanEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.DamageSource;
import org.bukkit.Bukkit;
import org.bukkit.entity.PigZombie;
import org.bukkit.event.entity.PigZombieAngerEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ZombiePigmanEntity.class)
public abstract class ZombiePigmanEntityMixin_1_15 extends ZombieEntityMixin {
// @formatter:off
@Shadow protected abstract boolean func_226547_i_(LivingEntity p_70835_1_);
@Shadow protected abstract int func_223336_ef();
// @formatter:on
public boolean attackEntityFrom(DamageSource damagesource, float f) {
if (this.isInvulnerableTo(damagesource)) {
return false;
}
Entity entity = damagesource.getTrueSource();
boolean result = super.attackEntityFrom(damagesource, f);
if (result && entity instanceof PlayerEntity && !((PlayerEntity) entity).isCreative() && this.canEntityBeSeen(entity)) {
this.func_226547_i_((LivingEntity) entity);
}
return result;
}
@Inject(method = "func_226547_i_", cancellable = true, at = @At("HEAD"))
private void arclight$anger(LivingEntity entity, CallbackInfoReturnable<Boolean> cir) {
PigZombieAngerEvent event = new PigZombieAngerEvent((PigZombie) this.getBukkitEntity(), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), this.func_223336_ef());
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
cir.setReturnValue(false);
} else {
arclight$capture = event.getNewAnger();
}
}
private transient int arclight$capture;
@Redirect(method = "func_226547_i_", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombiePigmanEntity;func_223336_ef()I"))
private int arclight$useAnger(ZombiePigmanEntity pigmanEntity) {
return arclight$capture;
}
}

View File

@ -0,0 +1,145 @@
package io.izzel.arclight.common.mixin.v1_15.entity.player;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.InternalEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.mixin.core.entity.LivingEntityMixin;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.server.ServerWorld;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerBedLeaveEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin_1_15 extends LivingEntityMixin implements PlayerEntityBridge {
// @formatter:off
@Shadow public abstract Either<PlayerEntity.SleepResult, Unit> trySleep(BlockPos at);
@Shadow public abstract void startSleeping(BlockPos p_213342_1_);
@Shadow public int sleepTimer;
@Shadow @Final public PlayerAbilities abilities;
// @formatter:on
@Shadow
public abstract void addStat(ResourceLocation stat);
@Override
public CraftHumanEntity bridge$getBukkitEntity() {
return (CraftHumanEntity) ((InternalEntityBridge) this).internal$getBukkitEntity();
}
private boolean arclight$forceSleep = false;
private Object arclight$processSleep = null;
private Either<PlayerEntity.SleepResult, Unit> getBedResult(BlockPos at, Direction direction) {
arclight$processSleep = true;
Either<PlayerEntity.SleepResult, Unit> either = this.trySleep(at);
arclight$processSleep = null;
return either;
}
public Either<PlayerEntity.SleepResult, Unit> sleep(BlockPos at, boolean force) {
arclight$forceSleep = force;
try {
return this.trySleep(at);
} finally {
arclight$forceSleep = false;
}
}
@Inject(method = "trySleep", cancellable = true, at = @At(value = "HEAD"))
public void arclight$onSleep(BlockPos at, CallbackInfoReturnable<Either<PlayerEntity.SleepResult, Unit>> cir) {
if (arclight$processSleep == null) {
Either<PlayerEntity.SleepResult, Unit> result = getBedResult(at, null);
if (result.left().orElse(null) == PlayerEntity.SleepResult.OTHER_PROBLEM) {
cir.setReturnValue(result);
return;
}
if (arclight$forceSleep) {
result = Either.right(Unit.INSTANCE);
}
if (this.bridge$getBukkitEntity() instanceof Player) {
result = CraftEventFactory.callPlayerBedEnterEvent((PlayerEntity) (Object) this, at, result);
if (result.left().isPresent()) {
cir.setReturnValue(result);
return;
}
}
this.startSleeping(at);
this.sleepTimer = 0;
if (this.world instanceof ServerWorld) {
((ServerWorld) this.world).updateAllPlayersSleepingFlag();
}
cir.setReturnValue(Either.right(Unit.INSTANCE));
}
}
@Inject(method = "trySleep", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;startSleeping(Lnet/minecraft/util/math/BlockPos;)V"))
public void arclight$preSleep(BlockPos at, CallbackInfoReturnable<Either<PlayerEntity.SleepResult, Unit>> cir) {
if (arclight$processSleep != null) {
cir.setReturnValue(Either.right(Unit.INSTANCE));
}
}
@Inject(method = "stopSleepInBed", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I"))
private void arclight$wakeup(boolean flag, boolean flag1, CallbackInfo ci) {
BlockPos blockPos = this.getBedPosition().orElse(null);
if (this.getBukkitEntity() instanceof Player) {
Player player = (Player) this.getBukkitEntity();
Block bed;
if (blockPos != null) {
bed = CraftBlock.at(this.world, blockPos);
} else {
bed = ((WorldBridge) this.world).bridge$getWorld().getBlockAt(player.getLocation());
}
PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, true);
Bukkit.getPluginManager().callEvent(event);
}
}
@Inject(method = "setSpawnPoint", remap = false, at = @At("RETURN"))
private void arclight$updateSpawnpoint(BlockPos pos, boolean p_226560_2_, boolean p_226560_3_, DimensionType dim, CallbackInfo ci) {
bridge$setSpawnWorld(pos == null ? "" : this.world.worldInfo.getWorldName());
}
@Inject(method = "startFallFlying", cancellable = true, at = @At("HEAD"))
private void arclight$startGlidingEvent(CallbackInfo ci) {
if (CraftEventFactory.callToggleGlideEvent((PlayerEntity) (Object) this, true).isCancelled()) {
this.setFlag(7, true);
this.setFlag(7, false);
ci.cancel();
}
}
@Inject(method = "stopFallFlying", cancellable = true, at = @At("HEAD"))
private void arclight$stopGlidingEvent(CallbackInfo ci) {
if (CraftEventFactory.callToggleGlideEvent((PlayerEntity) (Object) this, false).isCancelled()) {
ci.cancel();
}
}
@Override
public Either<PlayerEntity.SleepResult, Unit> bridge$trySleep(BlockPos at, boolean force) {
return sleep(at, force);
}
}

View File

@ -0,0 +1,326 @@
package io.izzel.arclight.common.mixin.v1_15.entity.player;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.InternalEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.network.play.ServerPlayNetHandlerBridge;
import io.izzel.arclight.common.bridge.world.TeleporterBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge;
import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.Blocks;
import net.minecraft.block.pattern.BlockPattern;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.play.ServerPlayNetHandler;
import net.minecraft.network.play.server.SChangeGameStatePacket;
import net.minecraft.network.play.server.SPlayEntityEffectPacket;
import net.minecraft.network.play.server.SPlaySoundEventPacket;
import net.minecraft.network.play.server.SPlayerAbilitiesPacket;
import net.minecraft.network.play.server.SRespawnPacket;
import net.minecraft.network.play.server.SServerDifficultyPacket;
import net.minecraft.potion.EffectInstance;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.management.PlayerInteractionManager;
import net.minecraft.server.management.PlayerList;
import net.minecraft.stats.Stats;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Teleporter;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.util.ITeleporter;
import net.minecraftforge.fml.hooks.BasicEventHooks;
import net.minecraftforge.fml.network.NetworkHooks;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.entity.CraftPlayer;
import org.bukkit.craftbukkit.v.util.BlockStateListPopulator;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.world.PortalCreateEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable;
import java.util.List;
@Mixin(ServerPlayerEntity.class)
public abstract class ServerPlayerEntityMixin_1_15 extends PlayerEntityMixin_1_15 implements ServerPlayerEntityBridge {
// @formatter:off
@Shadow public boolean invulnerableDimensionChange;
@Shadow public abstract ServerWorld getServerWorld();
@Shadow public boolean queuedEndExit;
@Shadow public ServerPlayNetHandler connection;
@Shadow private boolean seenCredits;
@Shadow @Final public MinecraftServer server;
@Shadow @Final public PlayerInteractionManager interactionManager;
@Shadow @Nullable private Vec3d enteredNetherPosition;
@Shadow public abstract void func_213846_b(ServerWorld p_213846_1_);
@Shadow public int lastExperience;
@Shadow private float lastHealth;
@Shadow private int lastFoodLevel;
// @formatter:on
@Override
public CraftPlayer bridge$getBukkitEntity() {
return (CraftPlayer) ((InternalEntityBridge) this).internal$getBukkitEntity();
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
@Nullable
public Entity changeDimension(DimensionType dim, ITeleporter teleporter) {
final DimensionType[] destination = {dim};
if (this.isSleeping()) return (ServerPlayerEntity) (Object) this;
if (!ForgeHooks.onTravelToDimension((ServerPlayerEntity) (Object) this, destination[0])) return null;
PlayerTeleportEvent.TeleportCause cause = bridge$getTeleportCause().orElse(PlayerTeleportEvent.TeleportCause.UNKNOWN);
// this.invulnerableDimensionChange = true;
DimensionType dimensiontype = this.dimension;
if (((DimensionTypeBridge) dimensiontype).bridge$getType() == DimensionType.THE_END && ((DimensionTypeBridge) destination[0]).bridge$getType() == DimensionType.OVERWORLD && teleporter instanceof Teleporter) { //Forge: Fix non-vanilla teleporters triggering end credits
this.invulnerableDimensionChange = true;
this.detach();
this.getServerWorld().removePlayer((ServerPlayerEntity) (Object) this, true); //Forge: The player entity is cloned so keep the data until after cloning calls copyFrom
if (!this.queuedEndExit) {
this.queuedEndExit = true;
this.connection.sendPacket(new SChangeGameStatePacket(4, this.seenCredits ? 0.0F : 1.0F));
this.seenCredits = true;
}
return (ServerPlayerEntity) (Object) this;
} else {
ServerWorld serverworld = this.server.getWorld(dimensiontype);
// this.dimension = destination;
final ServerWorld[] serverworld1 = {this.server.getWorld(destination[0])};
/*
WorldInfo worldinfo = serverworld1.getWorldInfo();
NetworkHooks.sendDimensionDataPacket(this.connection.netManager, (ServerPlayerEntity) (Object) this);
this.connection.sendPacket(new SRespawnPacket(destination, WorldInfo.byHashing(worldinfo.getSeed()), worldinfo.getGenerator(), this.interactionManager.getGameType()));
this.connection.sendPacket(new SServerDifficultyPacket(worldinfo.getDifficulty(), worldinfo.isDifficultyLocked()));
PlayerList playerlist = this.server.getPlayerList();
playerlist.updatePermissionLevel((ServerPlayerEntity) (Object) this);
serverworld.removeEntity((ServerPlayerEntity) (Object) this, true); //Forge: the player entity is moved to the new world, NOT cloned. So keep the data alive with no matching invalidate call.
this.revive();
*/
final PlayerList[] playerlist = new PlayerList[1];
Entity e = teleporter.placeEntity((ServerPlayerEntity) (Object) this, serverworld, serverworld1[0], this.rotationYaw, spawnPortal -> {//Forge: Start vanilla logic
double d0 = this.getPosX();
double d1 = this.getPosY();
double d2 = this.getPosZ();
float f = this.rotationPitch;
float f1 = this.rotationYaw;
double d3 = 8.0D;
float f2 = f1;
serverworld.getProfiler().startSection("moving");
if (serverworld1[0] != null) {
double moveFactor = serverworld.getDimension().getMovementFactor() / serverworld1[0].getDimension().getMovementFactor();
d0 *= moveFactor;
d2 *= moveFactor;
if (dimensiontype == DimensionType.OVERWORLD && destination[0] == DimensionType.THE_NETHER) {
this.enteredNetherPosition = this.getPositionVec();
} else if (dimensiontype == DimensionType.OVERWORLD && destination[0] == DimensionType.THE_END) {
BlockPos blockpos = serverworld1[0].getSpawnCoordinate();
d0 = blockpos.getX();
d1 = blockpos.getY();
d2 = blockpos.getZ();
f1 = 90.0F;
f = 0.0F;
}
}
Location enter = this.getBukkitEntity().getLocation();
Location exit = (serverworld1[0] == null) ? null : new Location(((ServerWorldBridge) serverworld1[0]).bridge$getWorld(), d0, d1, d2, f1, f);
PlayerPortalEvent event = new PlayerPortalEvent((Player) this.getBukkitEntity(), enter, exit, cause, 128, true, ((DimensionTypeBridge) destination[0]).bridge$getType() == DimensionType.THE_END ? 0 : 16);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null) {
return null;
}
exit = event.getTo();
if (exit == null) {
return null;
}
serverworld1[0] = ((CraftWorld) exit.getWorld()).getHandle();
d0 = exit.getX();
d1 = exit.getY();
d2 = exit.getZ();
// this.setLocationAndAngles(d0, d1, d2, f1, f);
serverworld.getProfiler().endSection();
serverworld.getProfiler().startSection("placing");
double d7 = Math.max(-2.9999872E7D, serverworld1[0].getWorldBorder().minX() + 16.0D);
double d4 = Math.max(-2.9999872E7D, serverworld1[0].getWorldBorder().minZ() + 16.0D);
double d5 = Math.min(2.9999872E7D, serverworld1[0].getWorldBorder().maxX() - 16.0D);
double d6 = Math.min(2.9999872E7D, serverworld1[0].getWorldBorder().maxZ() - 16.0D);
d0 = MathHelper.clamp(d0, d7, d5);
d2 = MathHelper.clamp(d2, d4, d6);
// this.setLocationAndAngles(d0, d1, d2, f1, f);
Vec3d exitVelocity = Vec3d.ZERO;
BlockPos exitPosition = new BlockPos(d0, d1, d2);
if (((DimensionTypeBridge) destination[0]).bridge$getType() == DimensionType.THE_END) {
int i = exitPosition.getX();
int j = exitPosition.getY() - 1;
int k = exitPosition.getZ();
if (event.getCanCreatePortal()) {
BlockStateListPopulator blockList = new BlockStateListPopulator(serverworld1[0]);
for (int j1 = -2; j1 <= 2; ++j1) {
for (int k1 = -2; k1 <= 2; ++k1) {
for (int l1 = -1; l1 < 3; ++l1) {
int i2 = i + k1 * 1 + j1 * 0;
int j2 = j + l1;
int k2 = k + k1 * 0 - j1 * 1;
boolean flag = l1 < 0;
blockList.setBlockState(new BlockPos(i2, j2, k2), flag ? Blocks.OBSIDIAN.getDefaultState() : Blocks.AIR.getDefaultState(), 3);
}
}
}
org.bukkit.World bworld = ((ServerWorldBridge) serverworld1[0]).bridge$getWorld();
PortalCreateEvent portalEvent = new PortalCreateEvent((List<BlockState>) (List) blockList.getList(), bworld, this.getBukkitEntity(), PortalCreateEvent.CreateReason.END_PLATFORM);
Bukkit.getPluginManager().callEvent(portalEvent);
if (!portalEvent.isCancelled()) {
blockList.updateList();
}
}
// this.setLocationAndAngles(i, j, k, f1, 0.0F);
exit.setX(i);
exit.setY(j);
exit.setZ(k);
// this.setMotion(Vec3d.ZERO);
exitVelocity = Vec3d.ZERO;
} else {
BlockPattern.PortalInfo portalInfo = ((TeleporterBridge) serverworld1[0].getDefaultTeleporter()).bridge$placeInPortal((ServerPlayerEntity) (Object) this, exitPosition, f2, event.getSearchRadius(), true);
if (spawnPortal && portalInfo == null && event.getCanCreatePortal()) {
if (((TeleporterBridge) serverworld1[0].getDefaultTeleporter()).bridge$makePortal((ServerPlayerEntity) (Object) this, exitPosition, event.getCreationRadius())) {
// serverworld1.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f2);
portalInfo = ((TeleporterBridge) serverworld1[0].getDefaultTeleporter()).bridge$placeInPortal((ServerPlayerEntity) (Object) this, exitPosition, f2, event.getSearchRadius(), true);
}
}
if (portalInfo == null) {
return null;
}
exitVelocity = portalInfo.motion;
exit.setX(portalInfo.pos.getX());
exit.setY(portalInfo.pos.getY());
exit.setZ(portalInfo.pos.getZ());
exit.setYaw(f2 + (float) portalInfo.rotation);
}
serverworld.getProfiler().endSection();
final PlayerTeleportEvent tpEvent = new PlayerTeleportEvent((Player) this.getBukkitEntity(), enter, exit, cause);
Bukkit.getServer().getPluginManager().callEvent(tpEvent);
if (tpEvent.isCancelled() || tpEvent.getTo() == null) {
return null;
}
exit = tpEvent.getTo();
if (exit == null) {
return null;
}
serverworld1[0] = ((CraftWorld) exit.getWorld()).getHandle();
this.invulnerableDimensionChange = true;
destination[0] = serverworld1[0].getDimension().getType();
this.dimension = destination[0];
WorldInfo worldinfo = serverworld1[0].getWorldInfo();
NetworkHooks.sendDimensionDataPacket(this.connection.netManager, (ServerPlayerEntity) (Object) this);
this.connection.sendPacket(new SRespawnPacket(destination[0], WorldInfo.byHashing(worldinfo.getSeed()), worldinfo.getGenerator(), this.interactionManager.getGameType()));
this.connection.sendPacket(new SServerDifficultyPacket(worldinfo.getDifficulty(), worldinfo.isDifficultyLocked()));
playerlist[0] = this.server.getPlayerList();
playerlist[0].updatePermissionLevel((ServerPlayerEntity) (Object) this);
serverworld.removeEntity((ServerPlayerEntity) (Object) this, true); //Forge: the player entity is moved to the new world, NOT cloned. So keep the data alive with no matching invalidate call.
this.revive();
this.setMotion(exitVelocity);
this.setWorld(serverworld1[0]);
serverworld1[0].addDuringPortalTeleport((ServerPlayerEntity) (Object) this);
this.func_213846_b(serverworld);
// this.connection.setPlayerLocation(this.getPosX(), this.getPosY(), this.getPosZ(), f1, f);
((ServerPlayNetHandlerBridge) this.connection).bridge$teleport(exit);
this.connection.captureCurrentPosition();
return (ServerPlayerEntity) (Object) this;//forge: this is part of the ITeleporter patch
});//Forge: End vanilla logic
if (e != (Object) this)
throw new IllegalArgumentException(String.format("Teleporter %s returned not the player entity but instead %s, expected PlayerEntity %s", teleporter, e, this));
this.interactionManager.setWorld(serverworld1[0]);
this.connection.sendPacket(new SPlayerAbilitiesPacket(this.abilities));
playerlist[0].sendWorldInfo((ServerPlayerEntity) (Object) this, serverworld1[0]);
playerlist[0].sendInventory((ServerPlayerEntity) (Object) this);
for (EffectInstance effectinstance : this.getActivePotionEffects()) {
this.connection.sendPacket(new SPlayEntityEffectPacket(this.getEntityId(), effectinstance));
}
this.connection.sendPacket(new SPlaySoundEventPacket(1032, BlockPos.ZERO, 0, false));
this.lastExperience = -1;
this.lastHealth = -1.0F;
this.lastFoodLevel = -1;
BasicEventHooks.firePlayerChangedDimensionEvent((ServerPlayerEntity) (Object) this, dimensiontype, destination[0]);
PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent((Player) this.getBukkitEntity(), ((WorldBridge) serverworld).bridge$getWorld());
Bukkit.getPluginManager().callEvent(changeEvent);
return (ServerPlayerEntity) (Object) this;
}
}
public Entity a(DimensionType dimensionmanager, final PlayerTeleportEvent.TeleportCause cause) {
bridge$pushChangeDimensionCause(cause);
return this.changeDimension(dimensionmanager);
}
@Override
public Either<PlayerEntity.SleepResult, Unit> sleep(BlockPos at, boolean force) {
return super.sleep(at, force).ifRight((p_213849_1_) -> {
this.addStat(Stats.SLEEP_IN_BED);
CriteriaTriggers.SLEPT_IN_BED.trigger((ServerPlayerEntity) (Object) this);
});
}
@Inject(method = "stopSleepInBed", cancellable = true, at = @At("HEAD"))
private void arclight$notWake(boolean flag, boolean flag1, CallbackInfo ci) {
if (!isSleeping()) ci.cancel();
}
@Override
public Entity bridge$changeDimension(DimensionType dimensionType, PlayerTeleportEvent.TeleportCause cause) {
return a(dimensionType, cause);
}
}

View File

@ -0,0 +1,15 @@
package io.izzel.arclight.common.mixin.v1_15.item.crafting;
import io.izzel.arclight.common.bridge.item.crafting.IRecipeBridge;
import net.minecraft.item.crafting.SpecialRecipe;
import org.bukkit.inventory.Recipe;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(SpecialRecipe.class)
public class SpecialRecipeMixin implements IRecipeBridge {
@Override
public Recipe bridge$toBukkitRecipe() {
return new org.bukkit.craftbukkit.v.inventory.CraftComplexRecipe((SpecialRecipe) (Object) this);
}
}

View File

@ -0,0 +1,139 @@
package io.izzel.arclight.common.mixin.v1_15.world;
import com.mojang.datafixers.util.Pair;
import io.izzel.arclight.common.bridge.world.ExplosionBridge;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.loot.LootContext;
import net.minecraft.world.storage.loot.LootParameters;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.block.BlockIgniteEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Collections;
import java.util.List;
import java.util.Random;
@Mixin(Explosion.class)
public abstract class ExplosionMixin_1_15 implements ExplosionBridge {
// @formatter:off
@Shadow @Final private World world;
@Shadow @Final private Explosion.Mode mode;
@Shadow @Mutable @Final private float size;
@Shadow @Final private List<BlockPos> affectedBlockPositions;
@Shadow @Final private double x;
@Shadow @Final private double y;
@Shadow @Final private double z;
@Shadow @Final private boolean causesFire;
@Shadow @Final private Random random;
@Shadow @Final public Entity exploder;
@Shadow private static void func_229976_a_(ObjectArrayList<Pair<ItemStack, BlockPos>> p_229976_0_, ItemStack p_229976_1_, BlockPos p_229976_2_) { }
@Accessor("exploder") public abstract Entity bridge$getExploder();
@Accessor("size") public abstract float bridge$getSize();
@Accessor("size") public abstract void bridge$setSize(float size);
@Accessor("mode") public abstract Explosion.Mode bridge$getMode();
// @formatter:on
public boolean wasCanceled = false;
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public void doExplosionB(boolean spawnParticles) {
if (this.world.isRemote) {
this.world.playSound(this.x, this.y, this.z, SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 4.0F, (1.0F + (this.world.rand.nextFloat() - this.world.rand.nextFloat()) * 0.2F) * 0.7F, false);
}
boolean flag = this.mode != Explosion.Mode.NONE;
if (spawnParticles) {
if (!(this.size < 2.0F) && flag) {
this.world.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
} else {
this.world.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
}
}
if (flag) {
ObjectArrayList<Pair<ItemStack, BlockPos>> objectarraylist = new ObjectArrayList<>();
Collections.shuffle(this.affectedBlockPositions, this.world.rand);
float yield = this.bridge$callBlockExplodeEvent();
if (Float.isNaN(yield)) {
this.wasCanceled = true;
return;
}
for (BlockPos blockpos : this.affectedBlockPositions) {
BlockState blockstate = this.world.getBlockState(blockpos);
Block block = blockstate.getBlock();
if (!blockstate.isAir(this.world, blockpos)) {
BlockPos blockpos1 = blockpos.toImmutable();
this.world.getProfiler().startSection("explosion_blocks");
if (blockstate.canDropFromExplosion(this.world, blockpos, (Explosion) (Object) this) && this.world instanceof ServerWorld) {
TileEntity tileentity = blockstate.hasTileEntity() ? this.world.getTileEntity(blockpos) : null;
LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerWorld) this.world)).withRandom(this.world.rand).withParameter(LootParameters.POSITION, blockpos).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, tileentity).withNullableParameter(LootParameters.THIS_ENTITY, this.exploder);
if (this.mode == Explosion.Mode.DESTROY || yield < 1.0F) {
lootcontext$builder.withParameter(LootParameters.EXPLOSION_RADIUS, 1.0F / yield);
}
blockstate.getDrops(lootcontext$builder).forEach((p_229977_2_) -> {
func_229976_a_(objectarraylist, p_229977_2_, blockpos1);
});
}
blockstate.onBlockExploded(this.world, blockpos, (Explosion) (Object) this);
this.world.getProfiler().endSection();
}
}
for (Pair<ItemStack, BlockPos> pair : objectarraylist) {
Block.spawnAsEntity(this.world, pair.getSecond(), pair.getFirst());
}
}
if (this.causesFire) {
for (BlockPos blockpos2 : this.affectedBlockPositions) {
if (this.random.nextInt(3) == 0 && this.world.getBlockState(blockpos2).isAir() && this.world.getBlockState(blockpos2.down()).isOpaqueCube(this.world, blockpos2.down())) {
BlockIgniteEvent event = CraftEventFactory.callBlockIgniteEvent(this.world, blockpos2.getX(), blockpos2.getY(), blockpos2.getZ(), (Explosion) (Object) this);
if (!event.isCancelled()) {
this.world.setBlockState(blockpos2, Blocks.FIRE.getDefaultState());
}
}
}
}
}
@Inject(method = "func_229976_a_", cancellable = true, at = @At("HEAD"))
private static void arclight$fix(ObjectArrayList<Pair<ItemStack, BlockPos>> p_229976_0_, ItemStack stack, BlockPos p_229976_2_, CallbackInfo ci) {
if (stack.isEmpty()) ci.cancel();
}
@Override
public boolean bridge$wasCancelled() {
return wasCanceled;
}
}

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.common.mixin.v1_15.world.dimension;
import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge;
import net.minecraft.world.World;
import net.minecraft.world.biome.IBiomeMagnifier;
import net.minecraft.world.dimension.Dimension;
@ -9,7 +10,7 @@ import org.spongepowered.asm.mixin.Mixin;
import java.util.function.BiFunction;
@Mixin(DimensionType.class)
public class DimensionTypeMixin_1_15 {
public class DimensionTypeMixin_1_15 implements DimensionTypeBridge {
protected void arclight$constructor(int idIn, String suffixIn, String directoryIn, BiFunction<World, DimensionType, ? extends Dimension> p_i49935_4_, boolean p_i49935_5_, IBiomeMagnifier p_i225789_6_) {
throw new RuntimeException();
@ -25,4 +26,9 @@ public class DimensionTypeMixin_1_15 {
public DimensionType getType() {
return (type == null) ? (DimensionType) (Object) this : type;
}
@Override
public DimensionType bridge$getType() {
return getType();
}
}

View File

@ -28,6 +28,7 @@
"block.KelpTopBlockMixin_1_15",
"block.LeavesBlockMixin_1_15",
"block.LeverBlockMixin_1_15",
"block.LilyPadBlockMixin_1_15",
"block.MushroomBlockMixin_1_15",
"block.NetherPortalBlockMixin_1_15",
"block.NetherWartBlockMixin_1_15",
@ -49,10 +50,20 @@
"command.impl.TimeCommandMixin",
"enchantment.FrostWalkerEnchantmentMixin_1_15",
"entity.EntityMixin_1_15",
"entity.LivingEntityMixin_1_15",
"entity.boss.WitherEntityMixin_1_15",
"entity.item.ArmorStandEntityMixin_1_15",
"entity.item.ItemEntityMixin_1_15",
"entity.monster.AbstractRaiderEntityMixin",
"entity.monster.RavagerEntityMixin_1_15",
"entity.monster.ShulkerEntityMixin_1_15",
"entity.passive.BeeEntity_AngerGoalMixin",
"entity.passive.BeeEntity_FindPollinationTargetGoalMixin",
"entity.passive.BeeEntityMixin",
"entity.player.PlayerEntityMixin_1_15",
"entity.player.ServerPlayerEntityMixin_1_15",
"item.crafting.SpecialRecipeMixin",
"world.ExplosionMixin_1_15",
"world.biome.BiomeContainerMixin",
"world.chunk.ChunkMixin_1_15",
"world.dimension.DimensionTypeMixin_1_15",

View File

@ -48,7 +48,6 @@
"block.IceBlockMixin",
"block.JukeBoxBlockMixin",
"block.LecternBlockMixin",
"block.LilyPadBlockMixin",
"block.MagmaBlockMixin",
"block.NetherPortalBlock_SizeMixin",
"block.NetherPortalBlockMixin",
@ -79,9 +78,7 @@
"command.arguments.EntitySelectorParserMixin",
"command.impl.EffectCommandMixin",
"command.impl.SummonCommandMixin",
"command.impl.TeleportCommandMixin",
"enchantment.DamageEnchantmentMixin",
"enchantment.FrostWalkerEnchantmentMixin",
"entity.AgeableEntityMixin",
"entity.AreaEffectCloudEntityMixin",
"entity.CreatureEntityMixin",
@ -109,7 +106,6 @@
"entity.ai.goal.TargetGoalMixin",
"entity.ai.goal.TemptGoalMixin",
"entity.ai.goal.TriggerSkeletonTrapGoalMixin",
"entity.boss.WitherEntityMixin",
"entity.boss.dragon.EnderDragonEntityMixin",
"entity.boss.dragon.phase.PhaseManagerMixin",
"entity.effect.LightningBoltEntityMixin",
@ -147,9 +143,6 @@
"entity.monster.IllusionerEntity_BlindnessSpellGoalMixin",
"entity.monster.IllusionerEntity_MirrorSpellGoalMixin",
"entity.monster.PhantomEntity_AttackPlayerGoalMixin",
"entity.monster.PillagerEntityMixin",
"entity.monster.RavagerEntityMixin",
"entity.monster.ShulkerEntityMixin",
"entity.monster.SilverfishEntity_HideInStoneGoalMixin",
"entity.monster.SilverfishEntity_SummonSilverfishGoalMixin",
"entity.monster.SlimeEntityMixin",
@ -175,7 +168,6 @@
"entity.passive.IronGolemEntityMixin",
"entity.passive.MooshroomEntityMixin",
"entity.passive.OcelotEntityMixin",
"entity.passive.PandaEntity_MateGoalMixin",
"entity.passive.PandaEntity_RevengeGoalMixin",
"entity.passive.PandaEntityMixin",
"entity.passive.ParrotEntityMixin",
@ -206,6 +198,7 @@
"entity.projectile.FishingBobberEntityMixin",
"entity.projectile.LlamaSpitEntityMixin",
"entity.projectile.PotionEntityMixin",
"entity.projectile.ProjectileItemEntityMixin",
"entity.projectile.ShulkerBulletEntityMixin",
"entity.projectile.SmallFireballEntityMixin",
"entity.projectile.SpectralArrowEntityMixin",
@ -344,9 +337,9 @@
"world.TrackedEntityMixin",
"world.WorldMixin",
"world.chunk.ChunkMixin",
"world.chunk.storage.ChunkLoaderMixin",
"world.chunk.storage.RegionFileCacheMixin",
"world.dimension.DimensionMixin",
"world.dimension.DimensionTypeMixin",
"world.gen.WorldGenRegionMixin",
"world.gen.feature.structure.SwampHutPieceMixin",
"world.raid.RaidManagerMixin",

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.block;
package io.izzel.arclight.impl.mixin.v1_14.block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LilyPadBlock.class)
public class LilyPadBlockMixin {
public class LilyPadBlockMixin_1_14 {
@Inject(method = "onEntityCollision", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;destroyBlock(Lnet/minecraft/util/math/BlockPos;Z)Z"))
public void arclight$entityChangeBlock(BlockState state, World worldIn, BlockPos pos, Entity entityIn, CallbackInfo ci) {

View File

@ -8,6 +8,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@ -21,14 +22,16 @@ import net.minecraftforge.common.ForgeHooks;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.event.entity.EntityPortalEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable;
import java.util.Random;
@Mixin(Entity.class)
public abstract class EntityMixin_1_14 {
public abstract class EntityMixin_1_14 implements EntityBridge {
// @formatter:off
@Shadow public World world;
@ -45,6 +48,12 @@ public abstract class EntityMixin_1_14 {
@Shadow public abstract void detach();
@Shadow public abstract EntityType<?> getType();
@Shadow public abstract void remove(boolean keepData);
@Shadow @Final protected EntityDataManager dataManager;
@Shadow public abstract boolean isInvisible();
@Shadow @Final protected Random rand;
@Shadow public abstract float getWidth();
@Shadow public abstract float getHeight();
@Shadow public abstract float getEyeHeight();
// @formatter:on
/**
@ -143,4 +152,9 @@ public abstract class EntityMixin_1_14 {
return null;
}
}
@Override
public double bridge$getEyeHeight() {
return this.posY + (double) this.getEyeHeight();
}
}

View File

@ -0,0 +1,278 @@
package io.izzel.arclight.impl.mixin.v1_14.entity;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.LivingEntityBridge;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.boss.WitherEntity;
import net.minecraft.entity.item.ExperienceOrbEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.potion.Effect;
import net.minecraft.potion.EffectInstance;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameRules;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.living.PotionEvent;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import javax.annotation.Nullable;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Mixin(LivingEntity.class)
public abstract class LivingEntityMixin_1_14 extends EntityMixin_1_14 implements LivingEntityBridge {
// @formatter:off
@Shadow @Final private static DataParameter<Integer> POTION_EFFECTS;
@Shadow @Final private static DataParameter<Boolean> HIDE_PARTICLES;
@Shadow @Final public Map<Effect, EffectInstance> activePotionsMap;
@Shadow public boolean potionsNeedUpdate;
@Shadow protected abstract void onFinishedPotionEffect(EffectInstance effect);
@Shadow protected abstract void onChangedPotionEffect(EffectInstance id, boolean reapply);
@Shadow protected abstract void updatePotionMetadata();
@Shadow public abstract boolean removePotionEffect(Effect effectIn);
@Shadow public abstract boolean isPotionApplicable(EffectInstance potioneffectIn);
@Shadow protected abstract void onNewPotionEffect(EffectInstance id);
@Shadow @Nullable public abstract EffectInstance removeActivePotionEffect(@Nullable Effect potioneffectin);
@Shadow public int deathTime;
@Shadow protected abstract boolean isPlayer();
@Shadow protected int recentlyHit;
@Shadow protected abstract boolean canDropLoot();
// @formatter:on
/**
* @author IzzelAliz
* @reason
*/
@SuppressWarnings("ConstantConditions")
@Overwrite
protected void onDeathUpdate() {
++this.deathTime;
if (this.deathTime >= 20 && !this.removed) {
if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT))) {
int i = this.bridge$getExpToDrop();
while (i > 0) {
int j = ExperienceOrbEntity.getXPSplit(i);
i -= j;
this.world.addEntity(new ExperienceOrbEntity(this.world, this.posX, this.posY, this.posZ, j));
}
this.bridge$setExpToDrop(0);
}
this.remove((Object) this instanceof ServerPlayerEntity); //Forge keep data until we revive player
for (int k = 0; k < 20; ++k) {
double d2 = this.rand.nextGaussian() * 0.02D;
double d0 = this.rand.nextGaussian() * 0.02D;
double d1 = this.rand.nextGaussian() * 0.02D;
this.world.addParticle(ParticleTypes.POOF, this.posX + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), this.posY + (double) (this.rand.nextFloat() * this.getHeight()), this.posZ + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), d2, d0, d1);
}
}
}
private boolean isTickingEffects = false;
private List<Map.Entry<Either<EffectInstance, Effect>, EntityPotionEffectEvent.Cause>> effectsToProcess = Lists.newArrayList();
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
protected void updatePotionEffects() {
this.isTickingEffects = true;
Iterator<Effect> iterator = this.activePotionsMap.keySet().iterator();
try {
while (iterator.hasNext()) {
Effect effect = iterator.next();
EffectInstance effectinstance = this.activePotionsMap.get(effect);
if (!effectinstance.tick((LivingEntity) (Object) this)) {
if (!this.world.isRemote && !MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionExpiryEvent((LivingEntity) (Object) this, effectinstance))) {
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION);
if (event.isCancelled()) {
continue;
}
iterator.remove();
this.onFinishedPotionEffect(effectinstance);
}
} else if (effectinstance.getDuration() % 600 == 0) {
this.onChangedPotionEffect(effectinstance, false);
}
}
} catch (ConcurrentModificationException ignored) {
}
isTickingEffects = false;
for (Map.Entry<Either<EffectInstance, Effect>, EntityPotionEffectEvent.Cause> e : effectsToProcess) {
Either<EffectInstance, Effect> either = e.getKey();
EntityPotionEffectEvent.Cause cause = e.getValue();
bridge$pushEffectCause(cause);
if (either.left().isPresent()) {
addPotionEffect(either.left().get());
} else {
removePotionEffect(either.right().get());
}
}
effectsToProcess.clear();
if (this.potionsNeedUpdate) {
if (!this.world.isRemote) {
this.updatePotionMetadata();
}
this.potionsNeedUpdate = false;
}
int i = this.dataManager.get(POTION_EFFECTS);
boolean flag1 = this.dataManager.get(HIDE_PARTICLES);
if (i > 0) {
boolean flag;
if (this.isInvisible()) {
flag = this.rand.nextInt(15) == 0;
} else {
flag = this.rand.nextBoolean();
}
if (flag1) {
flag &= this.rand.nextInt(5) == 0;
}
if (flag && i > 0) {
double d0 = (double) (i >> 16 & 255) / 255.0D;
double d1 = (double) (i >> 8 & 255) / 255.0D;
double d2 = (double) (i >> 0 & 255) / 255.0D;
this.world.addParticle(flag1 ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, this.posX + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), this.posY + this.rand.nextDouble() * (double) this.getHeight(), this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), d0, d1, d2);
}
}
}
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public boolean addPotionEffect(EffectInstance effectInstanceIn) {
EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN);
if (isTickingEffects) {
effectsToProcess.add(Maps.immutableEntry(Either.left(effectInstanceIn), cause));
return true;
}
if (!this.isPotionApplicable(effectInstanceIn)) {
return false;
} else {
EffectInstance effectinstance = this.activePotionsMap.get(effectInstanceIn.getPotion());
boolean override = false;
if (effectinstance != null) {
override = new EffectInstance(effectinstance).combine(effectInstanceIn);
}
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn, cause, override);
if (event.isCancelled()) {
return false;
}
MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionAddedEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn));
if (effectinstance == null) {
this.activePotionsMap.put(effectInstanceIn.getPotion(), effectInstanceIn);
this.onNewPotionEffect(effectInstanceIn);
return true;
} else if (event.isOverride()) {
effectinstance.combine(effectInstanceIn);
this.onChangedPotionEffect(effectinstance, true);
return true;
} else {
return false;
}
}
}
@SuppressWarnings("unused") // mock
public EffectInstance c(@Nullable Effect potioneffectin, EntityPotionEffectEvent.Cause cause) {
bridge$pushEffectCause(cause);
return removeActivePotionEffect(potioneffectin);
}
@Inject(method = "removeActivePotionEffect", at = @At("HEAD"))
public void arclight$clearActive(Effect effect, CallbackInfoReturnable<EffectInstance> cir) {
EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN);
if (isTickingEffects) {
effectsToProcess.add(Maps.immutableEntry(Either.right(effect), cause));
cir.setReturnValue(null);
return;
}
EffectInstance effectInstance = this.activePotionsMap.get(effect);
if (effectInstance == null) {
cir.setReturnValue(null);
return;
}
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectInstance, null, cause);
if (event.isCancelled()) {
cir.setReturnValue(null);
}
}
private transient boolean arclight$fallSuccess;
@Inject(method = "fall", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z"))
public void arclight$fall(float distance, float damageMultiplier, CallbackInfo ci) {
if (!arclight$fallSuccess) {
ci.cancel();
}
}
@Redirect(method = "fall", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z"))
public boolean arclight$fall(LivingEntity livingEntity, DamageSource source, float amount) {
return arclight$fallSuccess = livingEntity.attackEntityFrom(source, amount);
}
@Override
public void bridge$dropExperience() {
}
@Override
public void bridge$createWitherRose(LivingEntity entity) {
if (!this.world.isRemote && entity instanceof WitherEntity) {
boolean flag3 = false;
if (net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, (ServerPlayerEntity) (Object) this)) {
BlockPos blockposition = new BlockPos(this.posX, this.posY, this.posZ);
BlockState iblockdata = Blocks.WITHER_ROSE.getDefaultState();
if (this.world.getBlockState(blockposition).isAir() && iblockdata.isValidPosition(this.world, blockposition)) {
this.world.setBlockState(blockposition, iblockdata, 3);
flag3 = true;
}
}
if (!flag3) {
ItemEntity entityitem = new ItemEntity(this.world, this.posX, this.posY, this.posZ, new ItemStack(Items.WITHER_ROSE));
this.world.addEntity(entityitem);
}
}
}
}

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.entity.boss;
package io.izzel.arclight.impl.mixin.v1_14.entity.boss;
import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin;
import net.minecraft.block.BlockState;
@ -27,7 +27,7 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.List;
@Mixin(WitherEntity.class)
public abstract class WitherEntityMixin extends CreatureEntityMixin {
public abstract class WitherEntityMixin_1_14 extends CreatureEntityMixin {
// @formatter:off
@Shadow public abstract int getInvulTime();

View File

@ -0,0 +1,18 @@
package io.izzel.arclight.impl.mixin.v1_14.entity.item;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ItemEntity.class)
public class ItemEntityMixin_1_14 {
@Redirect(method = "func_213858_a", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/entity/item/ItemEntity;setItem(Lnet/minecraft/item/ItemStack;)V"))
private static void arclight$setNonEmpty(ItemEntity itemEntity, ItemStack stack) {
if (!stack.isEmpty()) {
itemEntity.setItem(stack);
}
}
}

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.entity.monster;
package io.izzel.arclight.impl.mixin.v1_14.entity.monster;
import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin;
import net.minecraft.entity.monster.PillagerEntity;
@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PillagerEntity.class)
public abstract class PillagerEntityMixin extends CreatureEntityMixin {
public abstract class PillagerEntityMixin_1_14 extends CreatureEntityMixin {
// @formatter:off
@Shadow public abstract Inventory getInventory();

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.entity.monster;
package io.izzel.arclight.impl.mixin.v1_14.entity.monster;
import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin;
import net.minecraft.block.Blocks;
@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(RavagerEntity.class)
public abstract class RavagerEntityMixin extends CreatureEntityMixin {
public abstract class RavagerEntityMixin_1_14 extends CreatureEntityMixin {
@Redirect(method = "livingTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;destroyBlock(Lnet/minecraft/util/math/BlockPos;Z)Z"))
private boolean arclight$entityChangeBlock(World world, BlockPos pos, boolean dropBlock) {

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.entity.monster;
package io.izzel.arclight.impl.mixin.v1_14.entity.monster;
import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin;
import net.minecraft.entity.monster.ShulkerEntity;
@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ShulkerEntity.class)
public abstract class ShulkerEntityMixin extends CreatureEntityMixin {
public abstract class ShulkerEntityMixin_1_14 extends CreatureEntityMixin {
@Inject(method = "notifyDataManagerChange", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/monster/ShulkerEntity;prevPosX:D"))
private void arclight$chunkCheck(DataParameter<?> key, CallbackInfo ci) {

View File

@ -0,0 +1,56 @@
package io.izzel.arclight.impl.mixin.v1_14.entity.monster;
import io.izzel.arclight.common.bridge.entity.EntityBridge;
import io.izzel.arclight.common.mixin.core.entity.monster.ZombieEntityMixin;
import net.minecraft.entity.Entity;
import net.minecraft.entity.monster.ZombiePigmanEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.DamageSource;
import org.bukkit.Bukkit;
import org.bukkit.entity.PigZombie;
import org.bukkit.event.entity.PigZombieAngerEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ZombiePigmanEntity.class)
public abstract class ZombiePigmanEntityMixin_1_14 extends ZombieEntityMixin {
// @formatter:off
@Shadow protected abstract boolean becomeAngryAt(Entity p_70835_1_);
@Shadow protected abstract int func_223336_ef();
// @formatter:on
public boolean attackEntityFrom(DamageSource damagesource, float f) {
if (this.isInvulnerableTo(damagesource)) {
return false;
}
Entity entity = damagesource.getTrueSource();
boolean result = super.attackEntityFrom(damagesource, f);
if (result && entity instanceof PlayerEntity && !((PlayerEntity) entity).isCreative() && this.canEntityBeSeen(entity)) {
this.becomeAngryAt(entity);
}
return result;
}
@Inject(method = "becomeAngryAt", cancellable = true, at = @At("HEAD"))
private void arclight$anger(Entity entity, CallbackInfoReturnable<Boolean> cir) {
PigZombieAngerEvent event = new PigZombieAngerEvent((PigZombie) this.getBukkitEntity(), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), this.func_223336_ef());
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
cir.setReturnValue(false);
} else {
arclight$capture = event.getNewAnger();
}
}
private transient int arclight$capture;
@Redirect(method = "becomeAngryAt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombiePigmanEntity;func_223336_ef()I"))
private int arclight$useAnger(ZombiePigmanEntity pigmanEntity) {
return arclight$capture;
}
}

View File

@ -0,0 +1,19 @@
package io.izzel.arclight.impl.mixin.v1_14.entity.passive;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.impl.mixin.v1_14.entity.EntityMixin_1_14;
import net.minecraft.entity.passive.OcelotEntity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(OcelotEntity.class)
public abstract class OcelotEntityMixin_1_14 extends EntityMixin_1_14 {
@Inject(method = "func_213525_dW", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z"))
private void arclight$spawnBaby(CallbackInfo ci) {
((WorldBridge) this.world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.OCELOT_BABY);
}
}

View File

@ -1,4 +1,4 @@
package io.izzel.arclight.common.mixin.core.entity.passive;
package io.izzel.arclight.impl.mixin.v1_14.entity.passive;
import io.izzel.arclight.common.bridge.entity.MobEntityBridge;
import net.minecraft.entity.passive.PandaEntity;

View File

@ -0,0 +1,138 @@
package io.izzel.arclight.impl.mixin.v1_14.entity.player;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.InternalEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.mixin.core.entity.LivingEntityMixin;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.server.ServerWorld;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v.block.CraftBlock;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerBedLeaveEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Optional;
@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixin_1_14 extends LivingEntityMixin implements PlayerEntityBridge {
// @formatter:off
@Shadow public abstract Either<PlayerEntity.SleepResult, Unit> trySleep(BlockPos at);
@Shadow public abstract void startSleeping(BlockPos p_213342_1_);
@Shadow public int sleepTimer;
@Shadow public abstract void addStat(ResourceLocation stat);
@Shadow @Final public PlayerAbilities abilities;
// @formatter:on
@Override
public CraftHumanEntity bridge$getBukkitEntity() {
return (CraftHumanEntity) ((InternalEntityBridge) this).internal$getBukkitEntity();
}
private boolean arclight$forceSleep = false;
private Object arclight$processSleep = null;
private Either<PlayerEntity.SleepResult, Unit> getBedResult(BlockPos at, Direction direction) {
arclight$processSleep = true;
Either<PlayerEntity.SleepResult, Unit> either = this.trySleep(at);
arclight$processSleep = null;
return either;
}
public Either<PlayerEntity.SleepResult, Unit> sleep(BlockPos at, boolean force) {
arclight$forceSleep = force;
try {
return this.trySleep(at);
} finally {
arclight$forceSleep = false;
}
}
@Inject(method = "trySleep", cancellable = true, at = @At(value = "HEAD"))
public void arclight$onSleep(BlockPos at, CallbackInfoReturnable<Either<PlayerEntity.SleepResult, Unit>> cir) {
if (arclight$processSleep == null) {
Either<PlayerEntity.SleepResult, Unit> result = getBedResult(at, null);
if (result.left().orElse(null) == PlayerEntity.SleepResult.OTHER_PROBLEM) {
cir.setReturnValue(result);
return;
}
if (arclight$forceSleep) {
result = Either.right(Unit.INSTANCE);
}
if (this.bridge$getBukkitEntity() instanceof Player) {
result = CraftEventFactory.callPlayerBedEnterEvent((PlayerEntity) (Object) this, at, result);
if (result.left().isPresent()) {
cir.setReturnValue(result);
return;
}
}
this.startSleeping(at);
this.sleepTimer = 0;
if (this.world instanceof ServerWorld) {
((ServerWorld) this.world).updateAllPlayersSleepingFlag();
}
cir.setReturnValue(Either.right(Unit.INSTANCE));
}
}
@Inject(method = "trySleep", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;startSleeping(Lnet/minecraft/util/math/BlockPos;)V"))
public void arclight$preSleep(BlockPos at, CallbackInfoReturnable<Either<PlayerEntity.SleepResult, Unit>> cir) {
if (arclight$processSleep != null) {
cir.setReturnValue(Either.right(Unit.INSTANCE));
}
}
@Inject(method = "wakeUpPlayer", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I"))
private void arclight$wakeup(boolean immediately, boolean updateWorldFlag, boolean setSpawn, CallbackInfo ci, Optional<BlockPos> optional) {
if (this.getBukkitEntity() instanceof Player) {
Player player = (Player) this.getBukkitEntity();
BlockPos blockposition2 = optional.orElse(null);
Block bed;
if (blockposition2 != null) {
bed = CraftBlock.at(this.world, blockposition2);
} else {
bed = ((WorldBridge) this.world).bridge$getWorld().getBlockAt(player.getLocation());
}
PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, setSpawn);
Bukkit.getPluginManager().callEvent(event);
arclight$setSpawn = event.shouldSetSpawnLocation();
}
}
private boolean arclight$setSpawn;
@ModifyVariable(method = "wakeUpPlayer", index = 3, name = "setSpawn", at = @At(value = "FIELD", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I"))
private boolean arclight$modifySpawn(boolean setSpawn) {
return arclight$setSpawn;
}
@Inject(method = "setSpawnPoint(Lnet/minecraft/util/math/BlockPos;Z)V", at = @At("RETURN"))
private void arclight$updateSpawnpoint(BlockPos pos, boolean forced, CallbackInfo ci) {
bridge$setSpawnWorld(pos == null ? "" : this.world.worldInfo.getWorldName());
}
@Override
public Either<PlayerEntity.SleepResult, Unit> bridge$trySleep(BlockPos at, boolean force) {
return sleep(at, force);
}
}

View File

@ -0,0 +1,264 @@
package io.izzel.arclight.impl.mixin.v1_14.entity.player;
import com.mojang.datafixers.util.Either;
import io.izzel.arclight.common.bridge.entity.InternalEntityBridge;
import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.play.ServerPlayNetHandler;
import net.minecraft.network.play.server.SChangeGameStatePacket;
import net.minecraft.network.play.server.SPlayEntityEffectPacket;
import net.minecraft.network.play.server.SPlaySoundEventPacket;
import net.minecraft.network.play.server.SPlayerAbilitiesPacket;
import net.minecraft.network.play.server.SRespawnPacket;
import net.minecraft.network.play.server.SServerDifficultyPacket;
import net.minecraft.potion.EffectInstance;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.management.PlayerInteractionManager;
import net.minecraft.server.management.PlayerList;
import net.minecraft.stats.Stats;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.WorldInfo;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v.CraftWorld;
import org.bukkit.craftbukkit.v.entity.CraftPlayer;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.craftbukkit.v.util.BlockStateListPopulator;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerPortalEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.world.PortalCreateEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import javax.annotation.Nullable;
import java.util.List;
@Mixin(ServerPlayerEntity.class)
public abstract class ServerPlayerEntityMixin_1_14 extends PlayerEntityMixin_1_14 implements ServerPlayerEntityBridge {
// @formatter:off
@Shadow public boolean invulnerableDimensionChange;
@Shadow public abstract ServerWorld func_71121_q();
@Shadow public boolean queuedEndExit;
@Shadow public ServerPlayNetHandler connection;
@Shadow private boolean seenCredits;
@Shadow @Final public MinecraftServer server;
@Shadow @Final public PlayerInteractionManager interactionManager;
@Shadow @Nullable private Vec3d enteredNetherPosition;
@Shadow public abstract void func_213846_b(ServerWorld p_213846_1_);
@Shadow public int lastExperience;
@Shadow private float lastHealth;
@Shadow private int lastFoodLevel;
// @formatter:on
@Override
public CraftPlayer bridge$getBukkitEntity() {
return (CraftPlayer) ((InternalEntityBridge) this).internal$getBukkitEntity();
}
/**
* @author IzzelAliz
* @reason
*/
@Nullable
@Overwrite
public Entity changeDimension(DimensionType dimensionmanager) {
PlayerTeleportEvent.TeleportCause cause = bridge$getTeleportCause().orElse(PlayerTeleportEvent.TeleportCause.UNKNOWN);
if (!net.minecraftforge.common.ForgeHooks.onTravelToDimension((ServerPlayerEntity) (Object) this, dimensionmanager))
return null;
if (this.isSleeping()) {
return (ServerPlayerEntity) (Object) this;
}
DimensionType dimensionmanager2 = this.dimension;
if (((DimensionTypeBridge) dimensionmanager2).bridge$getType() == DimensionType.THE_END && ((DimensionTypeBridge) dimensionmanager).bridge$getType() == DimensionType.OVERWORLD) {
this.invulnerableDimensionChange = true;
this.detach();
this.func_71121_q().removePlayer((ServerPlayerEntity) (Object) this, true);
if (!this.queuedEndExit) {
this.queuedEndExit = true;
this.connection.sendPacket(new SChangeGameStatePacket(4, this.seenCredits ? 0.0f : 1.0f));
this.seenCredits = true;
}
return (ServerPlayerEntity) (Object) this;
}
ServerWorld worldserver = this.server.func_71218_a(dimensionmanager2);
ServerWorld worldserver2 = this.server.func_71218_a(dimensionmanager);
WorldInfo worlddata = this.world.getWorldInfo();
double d0 = this.posX;
double d2 = this.posY;
double d3 = this.posZ;
float f = this.rotationPitch;
float f2 = this.rotationYaw;
double d4 = 8.0;
float f3 = f2;
worldserver.getProfiler().startSection("moving");
if (worldserver2 != null) {
if (dimensionmanager2 == DimensionType.OVERWORLD && dimensionmanager == DimensionType.THE_NETHER) {
this.enteredNetherPosition = new Vec3d(this.posX, this.posY, this.posZ);
d0 /= 8.0;
d3 /= 8.0;
} else if (dimensionmanager2 == DimensionType.THE_NETHER && dimensionmanager == DimensionType.OVERWORLD) {
d0 *= 8.0;
d3 *= 8.0;
} else if (dimensionmanager2 == DimensionType.OVERWORLD && dimensionmanager == DimensionType.THE_END) {
BlockPos blockposition = worldserver2.getSpawnCoordinate();
d0 = blockposition.getX();
d2 = blockposition.getY();
d3 = blockposition.getZ();
f2 = 90.0f;
f = 0.0f;
}
}
Location enter = this.getBukkitEntity().getLocation();
Location exit = (worldserver2 == null) ? null : new Location(((WorldBridge) worldserver2).bridge$getWorld(), d0, d2, d3, f2, f);
PlayerPortalEvent event = new PlayerPortalEvent((Player) this.getBukkitEntity(), enter, exit, cause);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null) {
return null;
}
exit = event.getTo();
if (exit == null) {
return null;
}
PlayerTeleportEvent tpEvent = new PlayerTeleportEvent((Player) this.getBukkitEntity(), enter, exit, cause);
Bukkit.getServer().getPluginManager().callEvent(tpEvent);
if (tpEvent.isCancelled() || tpEvent.getTo() == null) {
return null;
}
exit = tpEvent.getTo();
if (exit == null) {
return null;
}
worldserver2 = ((CraftWorld) exit.getWorld()).getHandle();
d0 = exit.getX();
d2 = exit.getY();
d3 = exit.getZ();
f2 = exit.getYaw();
f = exit.getPitch();
this.invulnerableDimensionChange = true;
dimensionmanager = worldserver2.getDimension().getType();
this.dimension = dimensionmanager;
net.minecraftforge.fml.network.NetworkHooks.sendDimensionDataPacket(this.connection.netManager, (ServerPlayerEntity) (Object) this);
this.connection.sendPacket(new SRespawnPacket(worldserver2.dimension.getType(), this.world.getWorldInfo().getGenerator(), this.interactionManager.getGameType()));
this.connection.sendPacket(new SServerDifficultyPacket(this.world.getDifficulty(), this.world.getWorldInfo().isDifficultyLocked()));
PlayerList playerlist = this.server.getPlayerList();
playerlist.updatePermissionLevel((ServerPlayerEntity) (Object) this);
worldserver.removePlayer((ServerPlayerEntity) (Object) this, true);
this.removed = false;
this.setLocationAndAngles(d0, d2, d3, f2, f);
worldserver.getProfiler().endSection();
worldserver.getProfiler().startSection("placing");
double d5 = Math.min(-2.9999872E7, worldserver2.getWorldBorder().minX() + 16.0);
double d6 = Math.min(-2.9999872E7, worldserver2.getWorldBorder().minZ() + 16.0);
double d7 = Math.min(2.9999872E7, worldserver2.getWorldBorder().maxX() - 16.0);
double d8 = Math.min(2.9999872E7, worldserver2.getWorldBorder().maxZ() - 16.0);
d0 = MathHelper.clamp(d0, d5, d7);
d3 = MathHelper.clamp(d3, d6, d8);
this.setLocationAndAngles(d0, d2, d3, f2, f);
if (((DimensionTypeBridge) dimensionmanager).bridge$getType() == DimensionType.THE_END) {
int i = MathHelper.floor(this.posX);
int j = MathHelper.floor(this.posY) - 1;
int k = MathHelper.floor(this.posZ);
boolean flag = true;
boolean flag2 = false;
BlockStateListPopulator blockList = new BlockStateListPopulator(worldserver2);
for (int l = -2; l <= 2; ++l) {
for (int i2 = -2; i2 <= 2; ++i2) {
for (int j2 = -1; j2 < 3; ++j2) {
int k2 = i + i2 * 1 + l * 0;
int l2 = j + j2;
int i3 = k + i2 * 0 - l * 1;
boolean flag3 = j2 < 0;
blockList.setBlockState(new BlockPos(k2, l2, i3), flag3 ? Blocks.OBSIDIAN.getDefaultState() : Blocks.AIR.getDefaultState(), 3);
}
}
}
org.bukkit.World bworld = ((WorldBridge) worldserver2).bridge$getWorld();
PortalCreateEvent portalEvent = new PortalCreateEvent((List) blockList.getList(), bworld, this.getBukkitEntity(), PortalCreateEvent.CreateReason.END_PLATFORM);
Bukkit.getPluginManager().callEvent(portalEvent);
if (!portalEvent.isCancelled()) {
blockList.updateList();
}
this.setLocationAndAngles(i, j, k, f2, 0.0f);
this.setMotion(Vec3d.ZERO);
} else if (!worldserver2.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f3)) {
worldserver2.getDefaultTeleporter().makePortal((ServerPlayerEntity) (Object) this);
worldserver2.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f3);
}
worldserver.getProfiler().endSection();
this.setWorld(worldserver2);
worldserver2.func_217447_b((ServerPlayerEntity) (Object) this);
this.func_213846_b(worldserver);
this.connection.setPlayerLocation(this.posX, this.posY, this.posZ, f2, f);
this.interactionManager.func_73080_a(worldserver2);
this.connection.sendPacket(new SPlayerAbilitiesPacket(this.abilities));
playerlist.func_72354_b((ServerPlayerEntity) (Object) this, worldserver2);
playerlist.sendInventory((ServerPlayerEntity) (Object) this);
for (EffectInstance mobeffect : this.getActivePotionEffects()) {
this.connection.sendPacket(new SPlayEntityEffectPacket(this.getEntityId(), mobeffect));
}
this.connection.sendPacket(new SPlaySoundEventPacket(1032, BlockPos.ZERO, 0, false));
this.lastExperience = -1;
this.lastHealth = -1.0f;
this.lastFoodLevel = -1;
PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent((Player) this.getBukkitEntity(), ((WorldBridge) worldserver).bridge$getWorld());
Bukkit.getPluginManager().callEvent(changeEvent);
net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerChangedDimensionEvent((ServerPlayerEntity) (Object) this, dimensionmanager2, dimensionmanager);
return (ServerPlayerEntity) (Object) this;
}
public Entity a(DimensionType dimensionmanager, final PlayerTeleportEvent.TeleportCause cause) {
bridge$pushChangeDimensionCause(cause);
return this.changeDimension(dimensionmanager);
}
@Override
public Either<PlayerEntity.SleepResult, Unit> sleep(BlockPos at, boolean force) {
return super.sleep(at, force).ifRight((p_213849_1_) -> {
this.addStat(Stats.SLEEP_IN_BED);
CriteriaTriggers.SLEPT_IN_BED.trigger((ServerPlayerEntity) (Object) this);
});
}
@Inject(method = "wakeUpPlayer", cancellable = true, at = @At("HEAD"))
private void arclight$notWake(boolean immediately, boolean updateWorldFlag, boolean setSpawn, CallbackInfo ci) {
if (!isSleeping()) ci.cancel();
}
@Override
public Entity bridge$changeDimension(DimensionType dimensionType, PlayerTeleportEvent.TeleportCause cause) {
return a(dimensionType, cause);
}
@Inject(method = "setElytraFlying", cancellable = true, at = @At("HEAD"))
private void arclight$beginGlide(CallbackInfo ci) {
if (CraftEventFactory.callToggleGlideEvent((ServerPlayerEntity) (Object) this, true).isCancelled()) {
ci.cancel();
}
}
@Inject(method = "clearElytraFlying", cancellable = true, at = @At("HEAD"))
private void arclight$endGlide(CallbackInfo ci) {
if (CraftEventFactory.callToggleGlideEvent((ServerPlayerEntity) (Object) this, false).isCancelled()) {
ci.cancel();
}
}
}

View File

@ -0,0 +1,136 @@
package io.izzel.arclight.impl.mixin.v1_14.world;
import io.izzel.arclight.common.bridge.world.ExplosionBridge;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.loot.LootContext;
import net.minecraft.world.storage.loot.LootParameters;
import org.bukkit.craftbukkit.v.event.CraftEventFactory;
import org.bukkit.event.block.BlockIgniteEvent;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
import java.util.Random;
@Mixin(Explosion.class)
public abstract class ExplosionMixin_1_14 implements ExplosionBridge {
// @formatter:off
@Shadow @Final private World world;
@Shadow @Final private Explosion.Mode mode;
@Shadow @Mutable @Final private float size;
@Shadow @Final private List<BlockPos> affectedBlockPositions;
@Shadow @Final private double x;
@Shadow @Final private double y;
@Shadow @Final private double z;
@Shadow @Final private boolean causesFire;
@Shadow @Final private Random random;
@Accessor("exploder") public abstract Entity bridge$getExploder();
@Accessor("size") public abstract float bridge$getSize();
@Accessor("size") public abstract void bridge$setSize(float size);
@Accessor("mode") public abstract Explosion.Mode bridge$getMode();
// @formatter:on
public boolean wasCanceled = false;
/**
* @author IzzelAliz
* @reason
*/
@Overwrite
public void doExplosionB(boolean spawnParticles) {
if (world.isRemote) {
this.world.playSound(this.x, this.y, this.z, SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 4.0F, (1.0F + (this.world.rand.nextFloat() - this.world.rand.nextFloat()) * 0.2F) * 0.7F, false);
}
boolean flag = this.mode != Explosion.Mode.NONE;
if (spawnParticles) {
if (!(this.size < 2.0F) && flag) {
this.world.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
} else {
this.world.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
}
}
if (flag) {
float yield = this.bridge$callBlockExplodeEvent();
if (Float.isNaN(yield)) {
this.wasCanceled = true;
return;
}
for (BlockPos blockpos : this.affectedBlockPositions) {
BlockState blockstate = this.world.getBlockState(blockpos);
Block block = blockstate.getBlock();
if (spawnParticles) {
double d0 = ((float) blockpos.getX() + this.world.rand.nextFloat());
double d1 = ((float) blockpos.getY() + this.world.rand.nextFloat());
double d2 = ((float) blockpos.getZ() + this.world.rand.nextFloat());
double d3 = d0 - this.x;
double d4 = d1 - this.y;
double d5 = d2 - this.z;
double d6 = MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
d3 = d3 / d6;
d4 = d4 / d6;
d5 = d5 / d6;
double d7 = 0.5D / (d6 / (double) this.size + 0.1D);
d7 = d7 * (double) (this.world.rand.nextFloat() * this.world.rand.nextFloat() + 0.3F);
d3 = d3 * d7;
d4 = d4 * d7;
d5 = d5 * d7;
this.world.addParticle(ParticleTypes.POOF, (d0 + this.x) / 2.0D, (d1 + this.y) / 2.0D, (d2 + this.z) / 2.0D, d3, d4, d5);
this.world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, d3, d4, d5);
}
if (!blockstate.isAir(this.world, blockpos)) {
if (this.world instanceof ServerWorld && blockstate.canDropFromExplosion(this.world, blockpos, (Explosion) (Object) this)) {
TileEntity tileentity = blockstate.hasTileEntity() ? this.world.getTileEntity(blockpos) : null;
LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerWorld) this.world)).withRandom(this.world.rand).withParameter(LootParameters.POSITION, blockpos).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, tileentity);
if (this.mode == Explosion.Mode.DESTROY || yield < 1.0F) {
lootcontext$builder.withParameter(LootParameters.EXPLOSION_RADIUS, 1.0F / yield);
}
Block.spawnDrops(blockstate, lootcontext$builder);
}
blockstate.onBlockExploded(this.world, blockpos, (Explosion) (Object) this);
}
}
}
if (this.causesFire) {
for (BlockPos blockPos : this.affectedBlockPositions) {
if (this.world.getBlockState(blockPos).isAir(world, blockPos) && this.world.getBlockState(blockPos.down()).isOpaqueCube(this.world, blockPos.down()) && this.random.nextInt(3) == 0) {
BlockIgniteEvent event = CraftEventFactory.callBlockIgniteEvent(this.world, blockPos.getX(), blockPos.getY(), blockPos.getZ(), (Explosion) (Object) this);
if (!event.isCancelled()) {
this.world.setBlockState(blockPos, Blocks.FIRE.getDefaultState());
}
}
}
}
}
@Override
public boolean bridge$wasCancelled() {
return wasCanceled;
}
}

View File

@ -1,5 +1,6 @@
package io.izzel.arclight.impl.mixin.v1_14.world.dimension;
import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge;
import net.minecraft.world.World;
import net.minecraft.world.dimension.Dimension;
import net.minecraft.world.dimension.DimensionType;
@ -8,7 +9,7 @@ import org.spongepowered.asm.mixin.Mixin;
import java.util.function.BiFunction;
@Mixin(DimensionType.class)
public class DimensionTypeMixin_1_14 {
public class DimensionTypeMixin_1_14 implements DimensionTypeBridge {
protected void arclight$constructor(int idIn, String suffixIn, String directoryIn, BiFunction<World, DimensionType, ? extends Dimension> p_i49935_4_, boolean p_i49935_5_) {
throw new RuntimeException();
@ -24,4 +25,9 @@ public class DimensionTypeMixin_1_14 {
public DimensionType getType() {
return (type == null) ? (DimensionType) (Object) this : type;
}
@Override
public DimensionType bridge$getType() {
return getType();
}
}

View File

@ -1,9 +1,10 @@
package io.izzel.arclight.server;
import io.izzel.arclight.api.Unsafe;
import io.izzel.arclight.forgeinstaller.ForgeInstaller;
import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper;
import io.izzel.arclight.api.ArclightVersion;
import io.izzel.arclight.api.EnumHelper;
import io.izzel.arclight.api.Unsafe;
import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper;
import io.izzel.arclight.forgeinstaller.ForgeInstaller;
import net.minecraftforge.server.ServerMain;
import org.apache.logging.log4j.LogManager;
@ -29,6 +30,7 @@ public class Main {
System.setProperty("log4j.jul.LoggerAdapter", "io.izzel.arclight.common.mod.util.ArclightLoggerAdapter");
LogManager.getLogger("Arclight").info("Loading mappings ...");
Objects.requireNonNull(ArclightRemapper.INSTANCE);
ArclightVersion.setVersion(ArclightVersion.v1_14);
ServerMain.main(args);
} catch (Exception e) {
e.printStackTrace();

View File

@ -29,6 +29,7 @@
"block.KelpTopBlockMixin_1_14",
"block.LeavesBlockMixin_1_14",
"block.LeverBlockMixin_1_14",
"block.LilyPadBlockMixin_1_14",
"block.MushroomBlockMixin_1_14",
"block.NetherPortalBlockMixin_1_14",
"block.NetherWartBlockMixin_1_14",
@ -48,7 +49,19 @@
"command.impl.TeleportCommandMixin_1_14",
"enchantment.FrostWalkerEnchantmentMixin_1_14",
"entity.EntityMixin_1_14",
"entity.LivingEntityMixin_1_14",
"entity.boss.WitherEntityMixin_1_14",
"entity.item.ArmorStandEntityMixin_1_14",
"entity.item.ItemEntityMixin_1_14",
"entity.monster.PillagerEntityMixin_1_14",
"entity.monster.RavagerEntityMixin_1_14",
"entity.monster.ShulkerEntityMixin_1_14",
"entity.monster.ZombiePigmanEntityMixin_1_14",
"entity.passive.OcelotEntityMixin_1_14",
"entity.passive.PandaEntity_MateGoalMixin",
"entity.player.PlayerEntityMixin_1_14",
"entity.player.ServerPlayerEntityMixin_1_14",
"world.ExplosionMixin_1_14",
"world.chunk.ChunkMixin_1_14",
"world.dimension.DimensionTypeMixin_1_14",
"world.server.TicketManagerMixin_1_14"