Skip to content

Commit

Permalink
Allow mods to add custom FeatureFlags
Browse files Browse the repository at this point in the history
  • Loading branch information
XFactHD committed Oct 23, 2024
1 parent dd989e5 commit 49d3b0a
Show file tree
Hide file tree
Showing 30 changed files with 1,343 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--- a/net/minecraft/client/gui/screens/worldselection/ExperimentsScreen.java
+++ b/net/minecraft/client/gui/screens/worldselection/ExperimentsScreen.java
@@ -50,6 +_,11 @@

@Override
protected void init() {
+ if (net.minecraft.world.flag.FeatureFlags.REGISTRY.hasAnyModdedFlags()) {
+ this.minecraft.setScreen(new net.neoforged.neoforge.client.gui.ScrollableExperimentsScreen(this.parent, this.packRepository, this.output));
+ return;
+ }
+
this.layout.addTitleHeader(TITLE, this.font);
LinearLayout linearlayout = this.layout.addToContents(LinearLayout.vertical());
linearlayout.addChild(new MultiLineTextWidget(INFO, this.font).setMaxWidth(310), p_293611_ -> p_293611_.paddingBottom(15));
28 changes: 28 additions & 0 deletions patches/net/minecraft/world/flag/FeatureFlag.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--- a/net/minecraft/world/flag/FeatureFlag.java
+++ b/net/minecraft/world/flag/FeatureFlag.java
@@ -3,9 +_,25 @@
public class FeatureFlag {
final FeatureFlagUniverse universe;
final long mask;
+ final int extMaskIndex;
+ final boolean modded;

+ /**
+ * @deprecated Neo: use {@link #FeatureFlag(FeatureFlagUniverse, int, int, boolean)} instead
+ */
+ @Deprecated
FeatureFlag(FeatureFlagUniverse p_249115_, int p_251067_) {
+ this(p_249115_, p_251067_, 0, false);
+ }
+
+ FeatureFlag(FeatureFlagUniverse p_249115_, int p_251067_, int offset, boolean modded) {
this.universe = p_249115_;
this.mask = 1L << p_251067_;
+ this.extMaskIndex = offset - 1;
+ this.modded = modded;
+ }
+
+ public boolean isModded() {
+ return modded;
}
}
44 changes: 44 additions & 0 deletions patches/net/minecraft/world/flag/FeatureFlagRegistry.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
--- a/net/minecraft/world/flag/FeatureFlagRegistry.java
+++ b/net/minecraft/world/flag/FeatureFlagRegistry.java
@@ -75,6 +_,18 @@
}, p_249796_ -> List.copyOf(this.toNames(p_249796_)));
}

+ public FeatureFlag getFlag(ResourceLocation name) {
+ return com.google.common.base.Preconditions.checkNotNull(this.names.get(name), "Flag %s was not registered", name);
+ }
+
+ public Map<ResourceLocation, FeatureFlag> getAllFlags() {
+ return this.names;
+ }
+
+ public boolean hasAnyModdedFlags() {
+ return this.names.values().stream().anyMatch(FeatureFlag::isModded);
+ }
+
public static class Builder {
private final FeatureFlagUniverse universe;
private int id;
@@ -88,11 +_,20 @@
return this.create(ResourceLocation.withDefaultNamespace(p_251782_));
}

+ /**
+ * @deprecated Neo: use {@link #create(ResourceLocation, boolean)} instead
+ */
+ @Deprecated
public FeatureFlag create(ResourceLocation p_250098_) {
- if (this.id >= 64) {
+ return create(p_250098_, false);
+ }
+
+ public FeatureFlag create(ResourceLocation p_250098_, boolean modded) {
+ if (this.id >= 64 && false) {
throw new IllegalStateException("Too many feature flags");
} else {
- FeatureFlag featureflag = new FeatureFlag(this.universe, this.id++);
+ FeatureFlag featureflag = new FeatureFlag(this.universe, this.id % FeatureFlagSet.MAX_CONTAINER_SIZE, this.id / FeatureFlagSet.MAX_CONTAINER_SIZE, modded);
+ this.id++;
FeatureFlag featureflag1 = this.flags.put(p_250098_, featureflag);
if (featureflag1 != null) {
throw new IllegalStateException("Duplicate feature flag " + p_250098_);
188 changes: 188 additions & 0 deletions patches/net/minecraft/world/flag/FeatureFlagSet.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
--- a/net/minecraft/world/flag/FeatureFlagSet.java
+++ b/net/minecraft/world/flag/FeatureFlagSet.java
@@ -7,14 +_,21 @@

public final class FeatureFlagSet {
private static final FeatureFlagSet EMPTY = new FeatureFlagSet(null, 0L);
+ private static final long[] EMPTY_EXT_MASK = new long[0];
public static final int MAX_CONTAINER_SIZE = 64;
@Nullable
private final FeatureFlagUniverse universe;
private final long mask;
+ private final long[] extendedMask;

private FeatureFlagSet(@Nullable FeatureFlagUniverse p_250433_, long p_251523_) {
+ this(p_250433_, p_251523_, EMPTY_EXT_MASK);
+ }
+
+ private FeatureFlagSet(@Nullable FeatureFlagUniverse p_250433_, long p_251523_, long[] extendedMask) {
this.universe = p_250433_;
this.mask = p_251523_;
+ this.extendedMask = extendedMask;
}

static FeatureFlagSet create(FeatureFlagUniverse p_251573_, Collection<FeatureFlag> p_251037_) {
@@ -22,7 +_,8 @@
return EMPTY;
} else {
long i = computeMask(p_251573_, 0L, p_251037_);
- return new FeatureFlagSet(p_251573_, i);
+ long[] extMask = computeExtendedMask(p_251573_, 0, 0L, p_251037_);
+ return new FeatureFlagSet(p_251573_, i, extMask);
}
}

@@ -31,16 +_,19 @@
}

public static FeatureFlagSet of(FeatureFlag p_252331_) {
- return new FeatureFlagSet(p_252331_.universe, p_252331_.mask);
+ long[] extMask = computeExtendedMask(p_252331_.universe, p_252331_.extMaskIndex, p_252331_.mask, java.util.List.of());
+ return new FeatureFlagSet(p_252331_.universe, p_252331_.extMaskIndex >= 0 ? 0L : p_252331_.mask, extMask);
}

public static FeatureFlagSet of(FeatureFlag p_251008_, FeatureFlag... p_249805_) {
- long i = p_249805_.length == 0 ? p_251008_.mask : computeMask(p_251008_.universe, p_251008_.mask, Arrays.asList(p_249805_));
- return new FeatureFlagSet(p_251008_.universe, i);
+ long i = p_249805_.length == 0 ? (p_251008_.extMaskIndex >= 0 ? 0L : p_251008_.mask) : computeMask(p_251008_.universe, p_251008_.extMaskIndex >= 0 ? 0L : p_251008_.mask, Arrays.asList(p_249805_));
+ long[] extMask = computeExtendedMask(p_251008_.universe, p_251008_.extMaskIndex, p_251008_.mask, p_249805_.length == 0 ? java.util.List.of() : Arrays.asList(p_249805_));
+ return new FeatureFlagSet(p_251008_.universe, i, extMask);
}

private static long computeMask(FeatureFlagUniverse p_249684_, long p_250982_, Iterable<FeatureFlag> p_251734_) {
for (FeatureFlag featureflag : p_251734_) {
+ if (featureflag.extMaskIndex >= 0) continue;
if (p_249684_ != featureflag.universe) {
throw new IllegalStateException("Mismatched feature universe, expected '" + p_249684_ + "', but got '" + featureflag.universe + "'");
}
@@ -51,8 +_,36 @@
return p_250982_;
}

+ private static long[] computeExtendedMask(FeatureFlagUniverse universe, int firstExtIndex, long firstMask, Iterable<FeatureFlag> otherFlags) {
+ long[] extMask = EMPTY_EXT_MASK;
+ if (firstExtIndex >= 0) {
+ extMask = new long[firstExtIndex + 1];
+ extMask[firstExtIndex] |= firstMask;
+ }
+ for (FeatureFlag flag : otherFlags) {
+ if (flag.extMaskIndex < 0) continue;
+ if (universe != flag.universe) {
+ throw new IllegalStateException("Mismatched feature universe, expected '" + universe + "', but got '" + flag.universe + "'");
+ }
+ if (flag.extMaskIndex >= extMask.length) {
+ extMask = Arrays.copyOfRange(extMask, 0, flag.extMaskIndex + 1);
+ }
+ extMask[flag.extMaskIndex] |= flag.mask;
+ }
+ return extMask;
+ }
+
public boolean contains(FeatureFlag p_249521_) {
- return this.universe != p_249521_.universe ? false : (this.mask & p_249521_.mask) != 0L;
+ if (this.universe != p_249521_.universe) {
+ return false;
+ }
+ if (p_249521_.extMaskIndex < 0) {
+ return (this.mask & p_249521_.mask) != 0L;
+ }
+ if (this.extendedMask.length > p_249521_.extMaskIndex) {
+ return (this.extendedMask[p_249521_.extMaskIndex] & p_249521_.mask) != 0L;
+ }
+ return false;
}

public boolean isEmpty() {
@@ -62,13 +_,33 @@
public boolean isSubsetOf(FeatureFlagSet p_249164_) {
if (this.universe == null) {
return true;
- } else {
- return this.universe != p_249164_.universe ? false : (this.mask & ~p_249164_.mask) == 0L;
+ } else if (this.universe == p_249164_.universe) {
+ int len = Math.max(this.extendedMask.length, p_249164_.extendedMask.length);
+ for (int i = 0; i < len; i++) {
+ long thisMask = i < this.extendedMask.length ? this.extendedMask[i] : 0L;
+ long otherMask = i < p_249164_.extendedMask.length ? p_249164_.extendedMask[i] : 0L;
+ if ((thisMask & ~otherMask) != 0L) {
+ return false;
+ }
+ }
+ return (this.mask & ~p_249164_.mask) == 0L;
}
+ return false;
}

public boolean intersects(FeatureFlagSet p_341635_) {
- return this.universe != null && p_341635_.universe != null && this.universe == p_341635_.universe ? (this.mask & p_341635_.mask) != 0L : false;
+ if (this.universe == null || p_341635_.universe == null || this.universe != p_341635_.universe) {
+ return false;
+ }
+ int len = Math.min(this.extendedMask.length, p_341635_.extendedMask.length);
+ for (int i = 0; i < len; i++) {
+ long thisMask = this.extendedMask[i];
+ long otherMask = p_341635_.extendedMask[i];
+ if ((thisMask & otherMask) != 0L) {
+ return true;
+ }
+ }
+ return (this.mask & p_341635_.mask) != 0L;
}

public FeatureFlagSet join(FeatureFlagSet p_251527_) {
@@ -79,7 +_,16 @@
} else if (this.universe != p_251527_.universe) {
throw new IllegalArgumentException("Mismatched set elements: '" + this.universe + "' != '" + p_251527_.universe + "'");
} else {
- return new FeatureFlagSet(this.universe, this.mask | p_251527_.mask);
+ long[] extMask = EMPTY_EXT_MASK;
+ if (this.extendedMask.length > 0 || p_251527_.extendedMask.length > 0) {
+ extMask = new long[Math.max(this.extendedMask.length, p_251527_.extendedMask.length)];
+ for (int i = 0; i < extMask.length; i++) {
+ long thisMask = i < this.extendedMask.length ? this.extendedMask[i] : 0L;
+ long otherMask = i < p_251527_.extendedMask.length ? p_251527_.extendedMask[i] : 0L;
+ extMask[i] = thisMask | otherMask;
+ }
+ }
+ return new FeatureFlagSet(this.universe, this.mask | p_251527_.mask, extMask);
}
}

@@ -90,7 +_,15 @@
throw new IllegalArgumentException("Mismatched set elements: '" + this.universe + "' != '" + p_341688_.universe + "'");
} else {
long i = this.mask & ~p_341688_.mask;
- return i == 0L ? EMPTY : new FeatureFlagSet(this.universe, i);
+ long[] extMask = EMPTY_EXT_MASK;
+ if (this.extendedMask.length > 0 || p_341688_.extendedMask.length > 0) {
+ extMask = new long[this.extendedMask.length];
+ for (int idx = 0; idx < extMask.length; idx++) {
+ long otherMask = idx < p_341688_.extendedMask.length ? p_341688_.extendedMask[idx] : 0L;
+ extMask[idx] = this.extendedMask[idx] & ~otherMask;
+ }
+ }
+ return i == 0L && extMask.length == 0 ? EMPTY : new FeatureFlagSet(this.universe, i, extMask);
}
}

@@ -99,7 +_,7 @@
if (this == p_248691_) {
return true;
} else {
- if (p_248691_ instanceof FeatureFlagSet featureflagset && this.universe == featureflagset.universe && this.mask == featureflagset.mask) {
+ if (p_248691_ instanceof FeatureFlagSet featureflagset && this.universe == featureflagset.universe && this.mask == featureflagset.mask && Arrays.equals(this.extendedMask, featureflagset.extendedMask)) {
return true;
}

@@ -109,6 +_,10 @@

@Override
public int hashCode() {
- return (int)HashCommon.mix(this.mask);
+ int hash = (int)HashCommon.mix(this.mask);
+ for (long extMask : this.extendedMask) {
+ hash = 13 * hash + (int) HashCommon.mix(extMask);
+ }
+ return hash;
}
}
10 changes: 10 additions & 0 deletions patches/net/minecraft/world/flag/FeatureFlags.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--- a/net/minecraft/world/flag/FeatureFlags.java
+++ b/net/minecraft/world/flag/FeatureFlags.java
@@ -37,6 +_,7 @@
TRADE_REBALANCE = featureflagregistry$builder.createVanilla("trade_rebalance");
REDSTONE_EXPERIMENTS = featureflagregistry$builder.createVanilla("redstone_experiments");
MINECART_IMPROVEMENTS = featureflagregistry$builder.createVanilla("minecart_improvements");
+ net.neoforged.neoforge.common.util.flag.FeatureFlagLoader.loadModdedFlags(featureflagregistry$builder);
REGISTRY = featureflagregistry$builder.build();
CODEC = REGISTRY.codec();
VANILLA_SET = FeatureFlagSet.of(VANILLA);
Loading

0 comments on commit 49d3b0a

Please sign in to comment.