diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/inventory/IInventoryBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/inventory/IInventoryBridge.java index 718f79b7..e2c2f6af 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/inventory/IInventoryBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/inventory/IInventoryBridge.java @@ -47,7 +47,6 @@ public interface IInventoryBridge { if (owner != null) { return owner.getInventory(); } else { - // ArclightMod.LOGGER.warn("No owner for inventory {}/{}", this, this.getClass()); return new CraftInventory((Container) this); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/ExplosionMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/ExplosionMixin.java index 6f93e04b..b9479267 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/ExplosionMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/ExplosionMixin.java @@ -81,6 +81,7 @@ public abstract class ExplosionMixin implements ExplosionBridge { @Shadow @Final private ExplosionDamageCalculator damageCalculator; @Shadow public abstract boolean interactsWithBlocks(); @Shadow @Nullable public abstract LivingEntity getIndirectSourceEntity(); + @Shadow public static float getSeenPercent(Vec3 p_46065_, Entity p_46066_) { return 0f; } // @formatter:on @Inject(method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)V", @@ -188,8 +189,11 @@ public abstract class ExplosionMixin implements ExplosionBridge { var parts = entity.getParts(); if (parts != null) { for (var part : parts) { - if (list.contains(part)) { - part.hurt(this.getDamageSource(), (float) ((int) ((d10 * d10 + d10) / 2.0D * 7.0D * (double) f3 + 1.0D))); + // Calculate damage separately for each part + double dist; + if (list.contains(part) && (dist = Math.sqrt(part.distanceToSqr(vec3d)) / f3) <= 1.0D) { + double dmg = (1.0D - dist) * getSeenPercent(vec3d, part); + part.hurt(this.getDamageSource(), (float) ((int) ((dmg * dmg + dmg) / 2.0D * 7.0D * (double) f3 + 1.0D))); } } } else { @@ -266,7 +270,7 @@ public abstract class ExplosionMixin implements ExplosionBridge { if (blockstate.canDropFromExplosion(this.level, blockpos, (Explosion) (Object) this) && this.level instanceof ServerLevel serverLevel) { BlockEntity tileentity = blockstate.hasBlockEntity() ? this.level.getBlockEntity(blockpos) : null; LootContext.Builder lootcontext$builder = new LootContext.Builder(serverLevel).withRandom(this.level.random).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockpos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, this.source); - if (this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY || yield < 1.0F) { + if (yield < 1.0F) { lootcontext$builder.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / yield); } @@ -321,13 +325,13 @@ public abstract class ExplosionMixin implements ExplosionBridge { float bukkitYield; if (exploder != null) { - EntityExplodeEvent event = new EntityExplodeEvent(exploder, location, blockList, this.blockInteraction == Explosion.BlockInteraction.DESTROY ? 1.0F / this.radius : 1.0F); + EntityExplodeEvent event = new EntityExplodeEvent(exploder, location, blockList, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F); Bukkit.getPluginManager().callEvent(event); cancelled = event.isCancelled(); bukkitBlocks = event.blockList(); bukkitYield = event.getYield(); } else { - BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.blockInteraction == Explosion.BlockInteraction.DESTROY ? 1.0F / this.radius : 1.0F); + BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F); Bukkit.getPluginManager().callEvent(event); cancelled = event.isCancelled(); bukkitBlocks = event.blockList(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java index 954c5d73..8566489d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java @@ -230,6 +230,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, public boolean persistentInvisibility = false; public BlockPos lastLavaContact; public int maxAirTicks = getDefaultMaxAirSupply(); + public boolean visibleByDefault = true; private CraftEntity bukkitEntity; @@ -547,6 +548,9 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, if (!this.persist) { compound.putBoolean("Bukkit.persist", this.persist); } + if (!this.visibleByDefault) { + compound.putBoolean("Bukkit.visibleByDefault", this.visibleByDefault); + } if (this.persistentInvisibility) { compound.putBoolean("Bukkit.invisible", this.persistentInvisibility); } @@ -573,6 +577,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, this.tickCount = compound.getInt("Spigot.ticksLived"); } this.persist = !compound.contains("Bukkit.persist") || compound.getBoolean("Bukkit.persist"); + this.visibleByDefault = !compound.contains("Bukkit.visibleByDefault") || compound.getBoolean("Bukkit.visibleByDefault"); // CraftBukkit end // CraftBukkit start - Reset world diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/HopperBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/HopperBlockEntityMixin.java index f34c3833..b8adf090 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/HopperBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/HopperBlockEntityMixin.java @@ -19,11 +19,14 @@ import net.minecraft.world.level.block.entity.Hopper; import net.minecraft.world.level.block.entity.HopperBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v.inventory.CraftInventory; import org.bukkit.craftbukkit.v.inventory.CraftInventoryDoubleChest; import org.bukkit.craftbukkit.v.inventory.CraftItemStack; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Item; +import org.bukkit.event.inventory.HopperInventorySearchEvent; import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.event.inventory.InventoryPickupItemEvent; import org.bukkit.inventory.Inventory; @@ -34,6 +37,7 @@ 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; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.ArrayList; import java.util.List; @@ -119,6 +123,30 @@ public abstract class HopperBlockEntityMixin extends LockableBlockEntityMixin { } } + private static Container runHopperInventorySearchEvent(Container inventory, CraftBlock hopper, CraftBlock searchLocation, HopperInventorySearchEvent.ContainerType containerType) { + var event = new HopperInventorySearchEvent((inventory != null) ? new CraftInventory(inventory) : null, containerType, hopper, searchLocation); + Bukkit.getServer().getPluginManager().callEvent(event); + CraftInventory craftInventory = (CraftInventory) event.getInventory(); + return (craftInventory != null) ? craftInventory.getInventory() : null; + } + + @Inject(method = "getAttachedContainer", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) + private static void arclight$searchTo(Level level, BlockPos pos, BlockState p_155595_, CallbackInfoReturnable cir, Direction direction) { + var container = cir.getReturnValue(); + var hopper = CraftBlock.at(level, pos); + var searchBlock = CraftBlock.at(level, pos.relative(direction)); + cir.setReturnValue(runHopperInventorySearchEvent(container, hopper, searchBlock, HopperInventorySearchEvent.ContainerType.DESTINATION)); + } + + @Inject(method = "getSourceContainer", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) + private static void arclight$searchFrom(Level level, Hopper hopper, CallbackInfoReturnable cir) { + var container = cir.getReturnValue(); + var blockPos = new BlockPos(hopper.getLevelX(), hopper.getLevelY(), hopper.getLevelZ()); + var hopperBlock = CraftBlock.at(level, blockPos); + var containerBlock = CraftBlock.at(level, blockPos.above()); + cir.setReturnValue(runHopperInventorySearchEvent(container, hopperBlock, containerBlock, HopperInventorySearchEvent.ContainerType.SOURCE)); + } + @Override public List getContents() { return this.items; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/ChunkGeneratorMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/ChunkGeneratorMixin.java index c3cac367..24ff2366 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/ChunkGeneratorMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/ChunkGeneratorMixin.java @@ -3,14 +3,27 @@ package io.izzel.arclight.common.mixin.core.world.level.chunk; import io.izzel.arclight.common.bridge.core.world.IWorldBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.bridge.core.world.level.levelgen.ChunkGeneratorBridge; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.LegacyRandomSource; +import net.minecraft.world.level.levelgen.RandomState; import net.minecraft.world.level.levelgen.WorldgenRandom; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.StructureSet; +import net.minecraft.world.level.levelgen.structure.StructureStart; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; +import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.generator.CraftLimitedRegion; +import org.bukkit.craftbukkit.v.generator.strucutre.CraftStructure; import org.bukkit.craftbukkit.v.util.RandomSourceWrapper; import org.bukkit.generator.BlockPopulator; import org.spongepowered.asm.mixin.Final; @@ -20,6 +33,10 @@ 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; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.function.Predicate; @Mixin(ChunkGenerator.class) public abstract class ChunkGeneratorMixin implements ChunkGeneratorBridge { @@ -34,6 +51,17 @@ public abstract class ChunkGeneratorMixin implements ChunkGeneratorBridge { this.addDecorations(level, chunkAccess, manager); } + @Inject(method = "tryGenerateStructure", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/StructureManager;setStartForStructure(Lnet/minecraft/core/SectionPos;Lnet/minecraft/world/level/levelgen/structure/Structure;Lnet/minecraft/world/level/levelgen/structure/StructureStart;Lnet/minecraft/world/level/chunk/StructureAccess;)V")) + private void arclight$structureSpawn(StructureSet.StructureSelectionEntry p_223105_, StructureManager manager, RegistryAccess registryAccess, RandomState p_223108_, StructureTemplateManager p_223109_, long p_223110_, ChunkAccess p_223111_, ChunkPos chunkPos, SectionPos p_223113_, CallbackInfoReturnable cir, + Structure structure, int i, HolderSet holderset, Predicate> predicate, StructureStart structurestart) { + var box = structurestart.getBoundingBox(); + var event = new org.bukkit.event.world.AsyncStructureSpawnEvent(((WorldBridge) ((IWorldBridge) manager.level).bridge$getMinecraftWorld()).bridge$getWorld(), CraftStructure.minecraftToBukkit(structure, registryAccess), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunkPos.x, chunkPos.z); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + cir.setReturnValue(true); + } + } + public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunkAccess, StructureManager structureFeatureManager, boolean vanilla) { if (vanilla) { this.applyBiomeDecoration(level, chunkAccess, structureFeatureManager); @@ -61,6 +89,6 @@ public abstract class ChunkGeneratorMixin implements ChunkGeneratorBridge { @Override public void bridge$setBiomeSource(BiomeSource biomeSource) { - this.biomeSource = biomeSource; + this.biomeSource = biomeSource; } } diff --git a/arclight-common/src/main/resources/META-INF/accesstransformer.cfg b/arclight-common/src/main/resources/META-INF/accesstransformer.cfg index 19d3749d..a044d11c 100644 --- a/arclight-common/src/main/resources/META-INF/accesstransformer.cfg +++ b/arclight-common/src/main/resources/META-INF/accesstransformer.cfg @@ -2,6 +2,7 @@ public net.minecraft.server.MinecraftServer$TimeProfiler (JI)V # TimeProfiler public net.minecraft.world.level.block.entity.SkullBlockEntity f_262250_ # noteBlockSound public net.minecraft.world.entity.player.Player f_36081_ # enchantmentSeed +public net.minecraft.world.level.StructureManager f_220460_ # level # Arclight 1.18.2 public-f net.minecraft.server.ReloadableServerResources f_206847_ # commands public net.minecraft.world.level.chunk.ChunkGenerator f_212255_