Skip to content

Commit c2c76c5

Browse files
committed
Fixed crash on 1.21.1 when a placed feature is null.
1 parent 199a439 commit c2c76c5

2 files changed

Lines changed: 111 additions & 6 deletions

File tree

neoforge/src/main/java/com/dtteam/dynamictrees/worldgen/biomemodifier/RunFeatureCancellersBiomeModifier.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,30 @@ public void modify(Holder<Biome> biome, Phase phase, ModifiableBiomeInfo.BiomeIn
4646

4747
PlacedFeature placedFeature = placedFeatureHolder.value();
4848

49-
return placedFeature.getFeatures().anyMatch(configuredFeature -> {
50-
for (FeatureCanceller featureCanceller : featureCancellations.getCancellers()) {
51-
if (featureCanceller.shouldCancel(configuredFeature, featureCancellations)) {
52-
return true;
53-
}
49+
try {
50+
var features = placedFeature.getFeatures();
51+
if (features == null) {
52+
return false;
5453
}
5554

55+
return features.filter(cf -> cf.config() != null).anyMatch(configuredFeature -> {
56+
for (FeatureCanceller featureCanceller : featureCancellations.getCancellers()) {
57+
try {
58+
if (featureCanceller.shouldCancel(configuredFeature, featureCancellations)) {
59+
return true;
60+
}
61+
} catch (NullPointerException e) {
62+
// This should be logged
63+
// In this case, we do not want a single FeatureCanceller to break the entire process.
64+
return false;
65+
}
66+
}
67+
return false;
68+
});
69+
} catch (NullPointerException e) {
70+
// I don't know how to log this
5671
return false;
57-
});
72+
}
5873
}));
5974
}
6075
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.ferreusveritas.dynamictrees.worldgen.biomemodifiers;
2+
3+
import com.ferreusveritas.dynamictrees.DynamicTrees;
4+
import com.ferreusveritas.dynamictrees.api.worldgen.BiomePropertySelectors;
5+
import com.ferreusveritas.dynamictrees.api.worldgen.FeatureCanceller;
6+
import com.ferreusveritas.dynamictrees.init.DTConfigs;
7+
import com.ferreusveritas.dynamictrees.init.DTRegistries;
8+
import com.ferreusveritas.dynamictrees.worldgen.BiomeDatabase;
9+
import com.ferreusveritas.dynamictrees.worldgen.FeatureCancellationRegistry;
10+
import com.mojang.serialization.Codec;
11+
import net.minecraft.core.Holder;
12+
import net.minecraft.core.Registry;
13+
import net.minecraft.core.registries.Registries;
14+
import net.minecraft.resources.ResourceKey;
15+
import net.minecraft.resources.ResourceLocation;
16+
import net.minecraft.tags.TagKey;
17+
import net.minecraft.world.level.biome.Biome;
18+
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
19+
import net.minecraftforge.common.world.BiomeGenerationSettingsBuilder;
20+
import net.minecraftforge.common.world.BiomeModifier;
21+
import net.minecraftforge.common.world.ModifiableBiomeInfo;
22+
23+
public class RunFeatureCancellersBiomeModifier implements BiomeModifier {
24+
public static final TagKey<PlacedFeature> FEATURE_CANCELLER_EXCLUSIONS_KEY = TagKey.create(Registries.PLACED_FEATURE,
25+
new ResourceLocation(DynamicTrees.MOD_ID, "feature_canceller_exclusions"));
26+
27+
@Override
28+
public void modify(Holder<Biome> biome, Phase phase, ModifiableBiomeInfo.BiomeInfo.Builder builder) {
29+
if (phase == Phase.REMOVE && DTConfigs.WORLD_GEN.get()) {
30+
ResourceKey<Biome> biomeKey = biome.unwrapKey().orElseThrow();
31+
BiomeGenerationSettingsBuilder generationSettings = builder.getGenerationSettings();
32+
33+
BiomePropertySelectors.NormalFeatureCancellation featureCancellations = new BiomePropertySelectors.NormalFeatureCancellation();
34+
35+
for (FeatureCancellationRegistry.Entry entry : FeatureCancellationRegistry.getCancellations()) {
36+
if (entry.biomes().containsKey(biomeKey)) {
37+
if (entry.operation() == BiomeDatabase.Operation.REPLACE)
38+
featureCancellations.reset();
39+
featureCancellations.addFrom(entry.cancellations());
40+
}
41+
}
42+
43+
// final ResourceLocation biomeName = biome.unwrapKey().map(ResourceKey::location).orElse(null);
44+
//
45+
// if (biomeName == null) {
46+
// return;
47+
// }
48+
//
49+
50+
featureCancellations.getDecorationSteps().forEach(stage -> generationSettings.getFeatures(stage).removeIf(placedFeatureHolder -> {
51+
// If you want a placed feature to be entirely excluded from cancellation by any feature cancellers,
52+
// add it to the dynamictrees:tags/worldgen/placed_feature/feature_canceller_exclusions tag.
53+
if (placedFeatureHolder.is(FEATURE_CANCELLER_EXCLUSIONS_KEY))
54+
return false;
55+
56+
PlacedFeature placedFeature = placedFeatureHolder.value();
57+
58+
try {
59+
var features = placedFeature.getFeatures();
60+
if (features == null) {
61+
return false;
62+
}
63+
64+
return features.filter(cf -> cf.config() != null).anyMatch(configuredFeature -> {
65+
for (FeatureCanceller featureCanceller : featureCancellations.getCancellers()) {
66+
try {
67+
if (featureCanceller.shouldCancel(configuredFeature, featureCancellations)) {
68+
return true;
69+
}
70+
} catch (NullPointerException e) {
71+
// This should be logged
72+
// In this case, we do not want a single FeatureCanceller to break the entire process.
73+
return false;
74+
}
75+
}
76+
return false;
77+
});
78+
} catch (NullPointerException e) {
79+
// I don't know how to log this
80+
return false;
81+
}
82+
}));
83+
}
84+
}
85+
86+
@Override
87+
public Codec<? extends BiomeModifier> codec() {
88+
return DTRegistries.RUN_FEATURE_CANCELLERS_BIOME_MODIFIER.get();
89+
}
90+
}

0 commit comments

Comments
 (0)