Skip to content

Commit

Permalink
Hardcode the filtering of positions to heal based on the whitelist se…
Browse files Browse the repository at this point in the history
…tting, whether the state is air, fire or tnt, and whether the state is excluded
  • Loading branch information
ArkoSammy12 committed Aug 18, 2024
1 parent 3ad9d64 commit c1e8d2d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package xd.arkosammy.creeperhealing.explosions.factories;

import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.util.Pair;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
Expand All @@ -14,10 +11,7 @@
import xd.arkosammy.creeperhealing.config.ConfigSettings;
import xd.arkosammy.creeperhealing.config.ConfigUtils;
import xd.arkosammy.creeperhealing.explosions.*;
import xd.arkosammy.creeperhealing.util.ExcludedBlocks;
import xd.arkosammy.creeperhealing.util.ExplosionUtils;
import xd.arkosammy.monkeyconfig.settings.BooleanSetting;
import xd.arkosammy.monkeyconfig.settings.list.StringListSetting;

import java.util.*;

Expand Down Expand Up @@ -123,29 +117,17 @@ public World getWorld() {

@Nullable
private List<AffectedBlock> processAffectedPositions(List<BlockPos> affectedPositions, World world) {
List<AffectedBlock> affectedBlocks = new ArrayList<>();
boolean whitelistEnabled = ConfigUtils.getSettingValue(ConfigSettings.ENABLE_WHITELIST.getSettingLocation(), BooleanSetting.class);
List<? extends String> whitelist = ConfigUtils.getSettingValue(ConfigSettings.WHITELIST.getSettingLocation(), StringListSetting.class);
for (BlockPos affectedPosition : affectedPositions) {
// Hardcoded exception. Place before all logic
BlockState affectedState = this.affectedStatesAndBlockEntities.get(affectedPosition).getLeft();
if (affectedState == null || ExcludedBlocks.isExcluded(affectedState)) {
continue;
}
boolean isStateUnhealable = affectedState.isAir() || affectedState.isOf(Blocks.TNT) || affectedState.isIn(BlockTags.FIRE);
if (isStateUnhealable) {
continue;
}
String affectedBlockIdentifier = Registries.BLOCK.getId(affectedState.getBlock()).toString();
boolean whitelistContainsIdentifier = whitelist.contains(affectedBlockIdentifier);
if (!whitelistEnabled || whitelistContainsIdentifier) {
BlockEntity affectedBlockEntity = affectedStatesAndBlockEntities.get(affectedPosition).getRight();
affectedBlocks.add(AffectedBlock.newInstance(affectedPosition, affectedState, affectedBlockEntity, world));
}
}
if (affectedBlocks.isEmpty()) {
List<BlockPos> positionsToHeal = ExplosionUtils.filterPositionsToHeal(affectedPositions, (pos) -> this.affectedStatesAndBlockEntities.get(pos).getLeft());
if (positionsToHeal.isEmpty()) {
return null;
}
List<AffectedBlock> affectedBlocks = new ArrayList<>();
for (BlockPos pos : positionsToHeal) {
BlockState affectedState = this.affectedStatesAndBlockEntities.get(pos).getLeft();
BlockEntity affectedBlockEntity = this.affectedStatesAndBlockEntities.get(pos).getRight();
AffectedBlock affectedBlock = AffectedBlock.newInstance(pos, affectedState, affectedBlockEntity, world);
affectedBlocks.add(affectedBlock);
}
List<AffectedBlock> sortedAffectedBlocks = ExplosionUtils.sortAffectedBlocks(affectedBlocks, world);
return sortedAffectedBlocks;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public abstract class ExplosionMixin implements ExplosionDuck {
@Unique
private final Map<BlockPos, Pair<BlockState, BlockEntity>> affectedStatesAndBlockEntities = new HashMap<>();

@Unique
private final Set<BlockPos> vanillaAffectedPositions = new HashSet<>();

@Unique
private final Set<BlockPos> indirectlyAffectedPositions = new HashSet<>();

Expand All @@ -65,7 +68,7 @@ public abstract class ExplosionMixin implements ExplosionDuck {

@Override
public boolean creeperhealing$shouldHeal() {
if (this.getAffectedBlocks().isEmpty()) {
if (this.vanillaAffectedPositions.isEmpty()) {
return false;
}
World.ExplosionSourceType explosionSourceType = (this.explosionSourceType);
Expand Down Expand Up @@ -96,8 +99,9 @@ private void collectAffectedBlockStatesAndBlockEntities(CallbackInfo ci) {
if (world.isClient()) {
return;
}
this.vanillaAffectedPositions.addAll(ExplosionUtils.filterPositionsToHeal(this.getAffectedBlocks(), (pos) -> this.world.getBlockState(pos)));
this.checkForIndirectlyAffectedPositions();
for (BlockPos pos : this.getAffectedBlocks()) {
for (BlockPos pos : this.vanillaAffectedPositions) {
this.affectedStatesAndBlockEntities.put(pos, new Pair<>(this.world.getBlockState(pos), this.world.getBlockEntity(pos)));
}
for (BlockPos pos : this.indirectlyAffectedPositions) {
Expand All @@ -121,11 +125,13 @@ private void emitExplosionContext(boolean particles, CallbackInfo ci) {
ExplosionUtils.DROP_BLOCK_ITEMS.set(true);
ExplosionUtils.DROP_CONTAINER_INVENTORY_ITEMS.set(true);
if (world.isClient()) {
this.vanillaAffectedPositions.clear();
this.affectedStatesAndBlockEntities.clear();
this.indirectlyAffectedPositions.clear();
return;
}
if (!this.creeperhealing$shouldHeal()) {
this.vanillaAffectedPositions.clear();
this.affectedStatesAndBlockEntities.clear();
this.indirectlyAffectedPositions.clear();
return;
Expand All @@ -147,7 +153,7 @@ private void emitExplosionContext(boolean particles, CallbackInfo ci) {
}
}
List<BlockPos> filteredAffectedPositions = new ArrayList<>();
for (BlockPos pos : this.getAffectedBlocks()) {
for (BlockPos pos : this.vanillaAffectedPositions) {
// Hardcoded exception, place before all other logic
BlockState state = this.affectedStatesAndBlockEntities.get(pos).getLeft();
if (ExcludedBlocks.isExcluded(state)) {
Expand All @@ -170,6 +176,7 @@ private void emitExplosionContext(boolean particles, CallbackInfo ci) {
this.explosionSourceType
);
ExplosionManagerRegistrar.getInstance().emitExplosionContext(DefaultExplosionManager.ID, explosionContext);
this.vanillaAffectedPositions.clear();
this.affectedStatesAndBlockEntities.clear();
this.indirectlyAffectedPositions.clear();
}
Expand Down Expand Up @@ -208,7 +215,7 @@ private void checkForIndirectlyAffectedPositions() {
for (BlockPos filteredPosition : edgeAffectedPositions) {
checkNeighbors(512, filteredPosition, newPositions, emptyWorld);
}
this.indirectlyAffectedPositions.addAll(newPositions);
this.indirectlyAffectedPositions.addAll(ExplosionUtils.filterPositionsToHeal(newPositions, (pos) -> this.world.getBlockState(pos)));
}

@Unique
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/xd/arkosammy/creeperhealing/util/ExplosionUtils.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package xd.arkosammy.creeperhealing.util;

import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.math.BlockPos;
Expand All @@ -16,8 +19,10 @@
import xd.arkosammy.creeperhealing.config.ConfigSettings;
import xd.arkosammy.creeperhealing.config.ConfigUtils;
import xd.arkosammy.monkeyconfig.settings.BooleanSetting;
import xd.arkosammy.monkeyconfig.settings.list.StringListSetting;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public final class ExplosionUtils {
Expand Down Expand Up @@ -52,6 +57,29 @@ private static boolean areAboveBlocksFree(World world, BlockPos pos, Entity enti
return true;
}

public static List<BlockPos> filterPositionsToHeal(Collection<BlockPos> positions, Function<BlockPos, BlockState> positionToStateMapper) {
List<BlockPos> affectedPositions = new ArrayList<>();
boolean whitelistEnabled = ConfigUtils.getSettingValue(ConfigSettings.ENABLE_WHITELIST.getSettingLocation(), BooleanSetting.class);
List<? extends String> whitelist = ConfigUtils.getSettingValue(ConfigSettings.WHITELIST.getSettingLocation(), StringListSetting.class);
for (BlockPos affectedPosition : positions) {
// Hardcoded exception. Place before all logic
BlockState affectedState = positionToStateMapper.apply(affectedPosition);
if (ExcludedBlocks.isExcluded(affectedState)) {
continue;
}
boolean stateCannotHeal = affectedState.isAir() || affectedState.isOf(Blocks.TNT) || affectedState.isIn(BlockTags.FIRE);
if (stateCannotHeal) {
continue;
}
String affectedBlockIdentifier = Registries.BLOCK.getId(affectedState.getBlock()).toString();
boolean whitelistContainsIdentifier = whitelist.contains(affectedBlockIdentifier);
if (!whitelistEnabled || whitelistContainsIdentifier) {
affectedPositions.add(affectedPosition);
}
}
return affectedPositions;
}

// The goal is to heal blocks inwards from the edge of the explosion, bottom to top, non-transparent blocks first
public static @NotNull List<AffectedBlock> sortAffectedBlocks(@NotNull List<AffectedBlock> affectedBlocksList, World world) {
List<AffectedBlock> sortedAffectedBlocks = new ArrayList<>(affectedBlocksList);
Expand Down

0 comments on commit c1e8d2d

Please sign in to comment.