From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samsuik <40902469+Samsuik@users.noreply.github.com> Date: Wed, 15 Nov 2023 23:18:38 +0000 Subject: [PATCH] Explosion Durable Blocks diff --git a/src/main/java/me/samsuik/sakura/explosion/durable/DurableBlockManager.java b/src/main/java/me/samsuik/sakura/explosion/durable/DurableBlockManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e52cae27c2bbf4fa02d49d1c69d8e1240fddfb81 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/explosion/durable/DurableBlockManager.java @@ -0,0 +1,43 @@ +package me.samsuik.sakura.explosion.durable; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import net.minecraft.core.BlockPos; + +import java.util.concurrent.TimeUnit; + +public final class DurableBlockManager { + private final Cache durableBlocks = CacheBuilder.newBuilder() + .expireAfterAccess(1, TimeUnit.MINUTES) + .maximumSize(65534) + .build(); + + public boolean damage(BlockPos pos, DurableMaterial material) { + DurableBlock block = this.durableBlocks.getIfPresent(pos); + if (block == null) { + this.durableBlocks.put(pos, block = new DurableBlock(material.durability())); + } + return block.damage(); + } + + public int durability(BlockPos pos, DurableMaterial material) { + final DurableBlock block = this.durableBlocks.getIfPresent(pos); + return block != null ? block.durability() : material.durability(); + } + + private static final class DurableBlock { + private int durability; + + public DurableBlock(int durability) { + this.durability = durability; + } + + public int durability() { + return this.durability; + } + + public boolean damage() { + return --this.durability <= 0; + } + } +} diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java index 4377fa2400c4320e0023ece230090a2a3b4b2ab6..9b66ac859619d3e79d5ab33939006b178699d474 100644 --- a/src/main/java/net/minecraft/world/item/BlockItem.java +++ b/src/main/java/net/minecraft/world/item/BlockItem.java @@ -47,8 +47,32 @@ public class BlockItem extends Item { this.block = block; } + // Sakura start - explosion durable blocks + private void sendBlockDurabilityToPlayer(UseOnContext context) { + Player player = context.getPlayer(); + BlockState state = context.getLevel().getBlockState(context.getClickedPos()); + Block block = state.getBlock(); + me.samsuik.sakura.explosion.durable.DurableMaterial material = context.getLevel().localConfig().config(context.getClickedPos()).durableMaterials.get(block); + + if (material != null) { + int remaining = context.getLevel().durabilityManager.durability(context.getClickedPos(), material); + int durability = material.durability(); + + player.getBukkitEntity().sendRichMessage( + me.samsuik.sakura.configuration.GlobalConfiguration.get().messages.durableBlockInteraction, + net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.unparsed("remaining", String.valueOf(remaining)), + net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.unparsed("durability", String.valueOf(durability)) + ); + } + } + @Override public InteractionResult useOn(UseOnContext context) { + if (this.getBlock() == net.minecraft.world.level.block.Blocks.POTATOES && context.getPlayer() != null) { + this.sendBlockDurabilityToPlayer(context); + } + // Sakura end - explosion durable blocks + InteractionResult enuminteractionresult = this.place(new BlockPlaceContext(context)); return !enuminteractionresult.consumesAction() && context.getItemInHand().has(DataComponents.CONSUMABLE) ? super.use(context.getLevel(), context.getPlayer(), context.getHand()) : enuminteractionresult; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 0301e304bb67d3a52de551442e425b83152fbabf..9fb78a9bd08521dff83b1f28be2421aa37af5898 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -844,6 +844,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // Paper end - optimise random ticking public final me.samsuik.sakura.entity.merge.EntityMergeHandler mergeHandler = new me.samsuik.sakura.entity.merge.EntityMergeHandler(); // Sakura - merge cannon entities public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(); // Sakura - explosion density cache + public final me.samsuik.sakura.explosion.durable.DurableBlockManager durabilityManager = new me.samsuik.sakura.explosion.durable.DurableBlockManager(); // Sakura - explosion durable blocks protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.function.Supplier sakuraWorldConfigCreator, java.util.concurrent.Executor executor) { // Sakura - sakura configuration files // Paper - create paper world config & Anti-Xray // Paper start - getblock optimisations - cache world height/sections diff --git a/src/main/java/net/minecraft/world/level/ServerExplosion.java b/src/main/java/net/minecraft/world/level/ServerExplosion.java index 74abe5fe92b3f1fe0139f4879fe5efa10d0623e0..278ca240491096514f4c48be56bcfe2d2356520e 100644 --- a/src/main/java/net/minecraft/world/level/ServerExplosion.java +++ b/src/main/java/net/minecraft/world/level/ServerExplosion.java @@ -134,7 +134,7 @@ public class ServerExplosion implements Explosion { BlockState blockState = ((ca.spottedleaf.moonrise.patches.getblock.GetBlockChunk)chunk).moonrise$getBlock(x, y, z); FluidState fluidState = blockState.getFluidState(); - Optional resistance = !calculateResistance ? Optional.empty() : this.damageCalculator.getBlockExplosionResistance((Explosion)(Object)this, this.level, pos, blockState, fluidState); + Optional resistance = !calculateResistance ? Optional.empty() : this.calculateBlockResistance(blockState, fluidState, pos); // Sakura - explosion durable blocks ret = new ca.spottedleaf.moonrise.patches.collisions.ExplosionBlockCache( key, pos, blockState, fluidState, @@ -393,6 +393,20 @@ public class ServerExplosion implements Explosion { // Paper end - collision optimisations } // Sakura end - specialised explosions + // Sakura start - explosion durable blocks + private Optional calculateBlockResistance(BlockState blockState, FluidState fluidState, BlockPos pos) { + if (!blockState.isAir()) { + Block block = blockState.getBlock(); + me.samsuik.sakura.explosion.durable.DurableMaterial material = this.level.localConfig().config(pos).durableMaterials.get(block); + + if (material != null && material.resistance() >= 0.0f && (this.level.sakuraConfig().cannons.explosion.allowNonTntBreakingDurableBlocks || this.source instanceof net.minecraft.world.entity.item.PrimedTnt)) { + return Optional.of(material.resistance()); + } + } + + return this.damageCalculator.getBlockExplosionResistance(this, this.level, pos, blockState, fluidState); + } + // Sakura end - explosion durable blocks public ServerExplosion(ServerLevel world, @Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, Vec3 pos, float power, boolean createFire, Explosion.BlockInteraction destructionType) { this.level = world; @@ -783,6 +797,16 @@ public class ServerExplosion implements Explosion { } } // CraftBukkit end + // Sakura start - explosion durable blocks + if (this.level.sakuraConfig().cannons.explosion.allowNonTntBreakingDurableBlocks || this.source instanceof net.minecraft.world.entity.item.PrimedTnt) { + me.samsuik.sakura.explosion.durable.DurableMaterial material = this.level.localConfig().config(blockposition).durableMaterials.get(block); + + if (material != null && material.durability() >= 0 && !this.level.durabilityManager.damage(blockposition, material)) { + iterator.remove(); + continue; + } + } + // Sakura end - explosion durable blocks this.level.getBlockState(blockposition).onExplosionHit(this.level, blockposition, this, (itemstack, blockposition1) -> { ServerExplosion.addOrAppendStack(list1, itemstack, blockposition1);