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..2e11ba36e9e820f17839d696e5d7d876e7437fbf --- /dev/null +++ b/src/main/java/me/samsuik/sakura/explosion/durable/DurableBlockManager.java @@ -0,0 +1,63 @@ +package me.samsuik.sakura.explosion.durable; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import me.samsuik.sakura.utils.objects.Expiry; +import net.minecraft.core.BlockPos; +import net.minecraft.server.MinecraftServer; + +public class DurableBlockManager { + + private final Long2ObjectOpenHashMap blocks = new Long2ObjectOpenHashMap<>(); + + public boolean damage(BlockPos pos, DurableMaterial material) { + long packed = pos.asLong(); + + DurableBlock block = this.blocks.computeIfAbsent(packed, k -> new DurableBlock( + material.durability(), + // expire after 1 minute + new Expiry(MinecraftServer.currentTickLong, 1200) + )); + + if (block.damage()) { + this.blocks.remove(packed); + return true; + } else { + block.getExpiry().refresh(MinecraftServer.currentTickLong); + return false; + } + } + + public int durability(BlockPos pos, DurableMaterial material) { + DurableBlock block = this.blocks.get(pos.asLong()); + return block != null ? block.getDurability() : material.durability(); + } + + public void expire(long tick) { + if (tick % 200 == 0) { + this.blocks.values().removeIf(block -> block.getExpiry().isExpired(tick)); + } + } + + private static class DurableBlock { + private int durability; + private final Expiry expiry; + + public DurableBlock(int durability, Expiry expiry) { + this.durability = durability; + this.expiry = expiry; + } + + public Expiry getExpiry() { + return expiry; + } + + public int getDurability() { + return durability; + } + + public boolean damage() { + return --this.durability <= 0; + } + } + +} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index d2b12606c4bd7edec4061f67e79bdedcee147fca..4c2dc25419662c491097a53f2a730b805269da05 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1582,6 +1582,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop resistance = !calculateResistance ? Optional.empty() : this.damageCalculator.getBlockExplosionResistance((Explosion)(Object)this, this.level, pos, blockState, fluidState); + // Sakura start - durable materials + if (calculateResistance) { + 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) { + resistance = Optional.of(material.resistance()); + } + } + // Sakura end + ret = new ExplosionBlockCache( key, pos, blockState, fluidState, (resistance.orElse(ZERO_RESISTANCE).floatValue() + 0.3f) * 0.3f, @@ -795,6 +806,14 @@ public class Explosion { BlockPos blockposition = (BlockPos) objectlistiterator.next(); BlockState iblockdata = this.level.getBlockState(blockposition); Block block = iblockdata.getBlock(); + // Sakura start - durable materials + me.samsuik.sakura.explosion.durable.DurableMaterial material = level.localConfig().config(blockposition).durableMaterials.get(block); + + if (material != null && material.durability() >= 0 && !level.durabilityManager.damage(blockposition, material)) { + objectlistiterator.remove(); + continue; + } + // Sakura end // CraftBukkit start - TNTPrimeEvent if (block instanceof net.minecraft.world.level.block.TntBlock) { Entity sourceEntity = this.source == null ? null : this.source; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 6fca6c3d8200251e24f3df886f17f35179b1f760..3d133380c70c6ef471dd42280bbd269ef72d2e6d 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -236,6 +236,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // Sakura end public final me.samsuik.sakura.entity.merge.MergeHistory mergeHistory = new me.samsuik.sakura.entity.merge.MergeHistory(); // Sakura public final me.samsuik.sakura.explosion.DensityCache densityCache = new me.samsuik.sakura.explosion.DensityCache(); + public final me.samsuik.sakura.explosion.durable.DurableBlockManager durabilityManager = new me.samsuik.sakura.explosion.durable.DurableBlockManager(); // Sakura start - limited get entities public void getLimitedEntities(Entity except, AABB box, Predicate predicate, List into, int limit, int search) {